[PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Andy Shevchenko
This is combined series of two things:
- split out the Intel LPSS specific driver from 8250_pci into 8250_lpss
- enable DMA support on Intel Quark UART

The patch has been tested on few Intel SoCs / platforms. In any case I would
like to ask Bryan to do independent test.

This is targeting serial subsystem, thus it would be nice to get and Ack from
Vinod first. Moreover, the series depends on [1] that is now in Vinod's
slave-dma tree.

That's why I asked Vinod to create immutable tag / branch for the [1] and the
dependants (at least one more, which is sata_dwc_460ex) can use it.

The series can be reached in the branch located at [2].

[1] http://www.spinics.net/lists/kernel/msg2244475.html
[2] https://bitbucket.org/andy-shev/linux/branch/topic%2Fdw%2Fqrk

Since v4:
- fix an issue what kernel test bot reported (lkp)
- add a list of supported SoC to Kconfig (Bryan)
- rename polarity -> hs_polarity (Bryan)

Since v3:
- rebase on top of recent tty-next branch
- add Reviewed-by tag from Bryan

Since v2:
- add tags
- rebase on top of new version of [1]

Since v1:
- address most of Peter's comments (mostly changelog to patch 8)
- add tag to patch 5
- drop patch 6 from the series to be separately dealt with

Andy Shevchenko (11):
  dmaengine: dw: keep copy of custom slave config in dwc
  dmaengine: dw: provide probe(), remove() stubs for users
  dmaengine: dw: set polarity of handshake interface
  dmaengine: dw: override LLP support if asked in platform data
  serial: 8250_dma: switch to new dmaengine_terminate_* API
  serial: 8250_dma: adjust DMA address of the UART
  serial: 8250: enable AFE on ports where FIFO is 16 bytes
  serial: 8250_lpss: split LPSS driver to separate module
  serial: 8250_lpss: move Quark code from PCI driver
  serial: 8250_lpss: enable MSI for Intel Quark
  serial: 8250_lpss: enable DMA on Intel Quark UART

 drivers/dma/dw/core.c                |  43 +++--
 drivers/dma/dw/regs.h                |   5 +-
 drivers/tty/serial/8250/8250.h       |   5 +
 drivers/tty/serial/8250/8250_dma.c   |  14 +-
 drivers/tty/serial/8250/8250_lpss.c  | 357 +++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_pci.c   | 257 +------------------------
 drivers/tty/serial/8250/8250_port.c  |   9 +-
 drivers/tty/serial/8250/Kconfig      |  16 +-
 drivers/tty/serial/8250/Makefile     |   1 +
 include/linux/dma/dw.h               |   5 +
 include/linux/platform_data/dma-dw.h |   4 +
 11 files changed, 430 insertions(+), 286 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_lpss.c

--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 10/11] serial: 8250_lpss: enable MSI for Intel Quark

Andy Shevchenko
Intel Quark SoC supports MSI for LPSS, in particular for UART. Enable MSI for
Intel Quark.

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250_lpss.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 3beb3aa..c83fd51 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -150,6 +150,17 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
  return 0;
 }
 
+static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+{
+ struct pci_dev *pdev = to_pci_dev(port->dev);
+
+ pci_enable_msi(pdev);
+
+ port->irq = pdev->irq;
+
+ return 0;
+}
+
 static bool lpss8250_dma_filter(struct dma_chan *chan, void *param)
 {
  struct dw_dma_slave *dws = param;
@@ -260,6 +271,7 @@ static const struct lpss8250_board byt_board = {
 static const struct lpss8250_board qrk_board = {
  .freq = 44236800,
  .base_baud = 2764800,
+ .setup = qrk_serial_setup,
 };
 
 #define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 08/11] serial: 8250_lpss: split LPSS driver to separate module

Andy Shevchenko
In reply to this post by Andy Shevchenko
The SoCs, such as Intel Braswell, have DesignWare UART IP. Split out the
support of such chips to a separate module which also will be used for Intel
Quark later.

The rationale to have the separate driver to be existing:
- Do not contaminate 8250_pci.c anymore with LPSS related quirks
- All of them are using same DMA engine and they are Designware IP which means
  that in the future we might share the code between 8250_dw.c and 8250_lpss.c
- It reduces the kernel memory footprint on non-X86 machines where 8250_pci.c
  is in use

Besides the split the driver also has been refactored, in particular a) the DMA
and port setup are separate functions, b) the two new structures lpss8250 and
lpss8250_board are introduced to keep necessary data instead of
pciserial_board, c) DMA parameters are passed to the DMA setup via mentioned
custom structure. Most of the changes are done due to the future support of
UART DMA on Intel Quark.

The Intel Quark UART DMA support is based on bits taking from BSP code
published by Intel earlier.

The driver does not use any specific power management. PCI core takes care of
the default behaviour during suspend and resume.

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250_lpss.c | 279 ++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_pci.c  | 242 ++-----------------------------
 drivers/tty/serial/8250/Kconfig     |  16 ++-
 drivers/tty/serial/8250/Makefile    |   1 +
 4 files changed, 303 insertions(+), 235 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_lpss.c

diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
new file mode 100644
index 0000000..77cf7e3
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -0,0 +1,279 @@
+/*
+ * 8250_lpss.c - Driver for UART on Intel Braswell and various other Intel SoCs
+ *
+ * Copyright (C) 2016 Intel Corporation
+ * Author: Andy Shevchenko <[hidden email]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/rational.h>
+
+#include <linux/dmaengine.h>
+#include <linux/platform_data/dma-dw.h>
+
+#include "8250.h"
+
+#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a
+#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c
+
+#define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
+#define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
+
+#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
+#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
+
+/* Intel LPSS specific registers */
+
+#define BYT_PRV_CLK 0x800
+#define BYT_PRV_CLK_EN BIT(0)
+#define BYT_PRV_CLK_M_VAL_SHIFT 1
+#define BYT_PRV_CLK_N_VAL_SHIFT 16
+#define BYT_PRV_CLK_UPDATE BIT(31)
+
+#define BYT_TX_OVF_INT 0x820
+#define BYT_TX_OVF_INT_MASK BIT(1)
+
+struct lpss8250;
+
+struct lpss8250_board {
+ unsigned long freq;
+ unsigned int base_baud;
+ int (*setup)(struct lpss8250 *, struct uart_port *p);
+};
+
+struct lpss8250 {
+ int line;
+ struct lpss8250_board *board;
+
+ /* DMA parameters */
+ struct uart_8250_dma dma;
+ struct dw_dma_slave dma_param;
+ u8 dma_maxburst;
+};
+
+static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
+    struct ktermios *old)
+{
+ unsigned int baud = tty_termios_baud_rate(termios);
+ struct lpss8250 *lpss = p->private_data;
+ unsigned long fref = lpss->board->freq, fuart = baud * 16;
+ unsigned long w = BIT(15) - 1;
+ unsigned long m, n;
+ u32 reg;
+
+ /* Gracefully handle the B0 case: fall back to B9600 */
+ fuart = fuart ? fuart : 9600 * 16;
+
+ /* Get Fuart closer to Fref */
+ fuart *= rounddown_pow_of_two(fref / fuart);
+
+ /*
+ * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
+ * dividers must be adjusted.
+ *
+ * uartclk = (m / n) * 100 MHz, where m <= n
+ */
+ rational_best_approximation(fuart, fref, w, w, &m, &n);
+ p->uartclk = fuart;
+
+ /* Reset the clock */
+ reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
+ writel(reg, p->membase + BYT_PRV_CLK);
+ reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
+ writel(reg, p->membase + BYT_PRV_CLK);
+
+ p->status &= ~UPSTAT_AUTOCTS;
+ if (termios->c_cflag & CRTSCTS)
+ p->status |= UPSTAT_AUTOCTS;
+
+ serial8250_do_set_termios(p, termios, old);
+}
+
+static unsigned int byt_get_mctrl(struct uart_port *port)
+{
+ unsigned int ret = serial8250_do_get_mctrl(port);
+
+ /* Force DCD and DSR signals to permanently be reported as active */
+ ret |= TIOCM_CAR | TIOCM_DSR;
+
+ return ret;
+}
+
+static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
+{
+ struct dw_dma_slave *param = &lpss->dma_param;
+ struct uart_8250_port *up = up_to_u8250p(port);
+ struct pci_dev *pdev = to_pci_dev(port->dev);
+ struct pci_dev *dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_BYT_UART1:
+ case PCI_DEVICE_ID_INTEL_BSW_UART1:
+ case PCI_DEVICE_ID_INTEL_BDW_UART1:
+ param->src_id = 3;
+ param->dst_id = 2;
+ break;
+ case PCI_DEVICE_ID_INTEL_BYT_UART2:
+ case PCI_DEVICE_ID_INTEL_BSW_UART2:
+ case PCI_DEVICE_ID_INTEL_BDW_UART2:
+ param->src_id = 5;
+ param->dst_id = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ param->dma_dev = &dma_dev->dev;
+ param->m_master = 0;
+ param->p_master = 1;
+
+ /* TODO: Detect FIFO size automaticaly for DesignWare 8250 */
+ port->fifosize = 64;
+ up->tx_loadsz = 64;
+
+ lpss->dma_maxburst = 16;
+
+ port->set_termios = byt_set_termios;
+ port->get_mctrl = byt_get_mctrl;
+
+ /* Disable TX counter interrupts */
+ writel(BYT_TX_OVF_INT_MASK, port->membase + BYT_TX_OVF_INT);
+
+ return 0;
+}
+
+static bool lpss8250_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct dw_dma_slave *dws = param;
+
+ if (dws->dma_dev != chan->device->dev)
+ return false;
+
+ chan->private = dws;
+ return true;
+}
+
+static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port)
+{
+ struct uart_8250_dma *dma = &lpss->dma;
+ struct dw_dma_slave *rx_param, *tx_param;
+ struct device *dev = port->port.dev;
+
+ rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
+ if (!rx_param)
+ return -ENOMEM;
+
+ tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
+ if (!tx_param)
+ return -ENOMEM;
+
+ *rx_param = lpss->dma_param;
+ dma->rxconf.src_maxburst = lpss->dma_maxburst;
+
+ *tx_param = lpss->dma_param;
+ dma->txconf.dst_maxburst = lpss->dma_maxburst;
+
+ dma->fn = lpss8250_dma_filter;
+ dma->rx_param = rx_param;
+ dma->tx_param = tx_param;
+
+ port->dma = dma;
+ return 0;
+}
+
+static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct uart_8250_port uart;
+ struct lpss8250 *lpss;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ pci_set_master(pdev);
+
+ lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL);
+ if (!lpss)
+ return -ENOMEM;
+
+ lpss->board = (struct lpss8250_board *)id->driver_data;
+
+ memset(&uart, 0, sizeof(struct uart_8250_port));
+
+ uart.port.dev = &pdev->dev;
+ uart.port.irq = pdev->irq;
+ uart.port.private_data = lpss;
+ uart.port.type = PORT_16550A;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.regshift = 2;
+ uart.port.uartclk = lpss->board->base_baud * 16;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
+ uart.capabilities = UART_CAP_FIFO | UART_CAP_AFE;
+ uart.port.mapbase = pci_resource_start(pdev, 0);
+ uart.port.membase = pcim_iomap(pdev, 0, 0);
+ if (!uart.port.membase)
+ return -ENOMEM;
+
+ ret = lpss->board->setup(lpss, &uart.port);
+ if (ret)
+ return ret;
+
+ ret = lpss8250_dma_setup(lpss, &uart);
+ if (ret)
+ return ret;
+
+ ret = serial8250_register_8250_port(&uart);
+ if (ret < 0)
+ return ret;
+
+ lpss->line = ret;
+
+ pci_set_drvdata(pdev, lpss);
+ return 0;
+}
+
+static void lpss8250_remove(struct pci_dev *pdev)
+{
+ struct lpss8250 *lpss = pci_get_drvdata(pdev);
+
+ serial8250_unregister_port(lpss->line);
+}
+
+static const struct lpss8250_board byt_board = {
+ .freq = 100000000,
+ .base_baud = 2764800,
+ .setup = byt_serial_setup,
+};
+
+#define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
+
+static const struct pci_device_id pci_ids[] = {
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART1, byt_board),
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART2, byt_board),
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART1, byt_board),
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART2, byt_board),
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART1, byt_board),
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART2, byt_board),
+ { },
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver lpss8250_pci_driver = {
+ .name           = "8250_lpss",
+ .id_table       = pci_ids,
+ .probe          = lpss8250_probe,
+ .remove         = lpss8250_remove,
+};
+
+module_pci_driver(lpss8250_pci_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel LPSS UART driver");
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 8dd250f..bb4df5d 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -21,14 +21,10 @@
 #include <linux/serial_core.h>
 #include <linux/8250_pci.h>
 #include <linux/bitops.h>
-#include <linux/rational.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 
-#include <linux/dmaengine.h>
-#include <linux/platform_data/dma-dw.h>
-
 #include "8250.h"
 
 /*
@@ -1349,160 +1345,6 @@ ce4100_serial_setup(struct serial_private *priv,
  return ret;
 }
 
-#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a
-#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c
-
-#define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
-#define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
-
-#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
-#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
-
-#define BYT_PRV_CLK 0x800
-#define BYT_PRV_CLK_EN (1 << 0)
-#define BYT_PRV_CLK_M_VAL_SHIFT 1
-#define BYT_PRV_CLK_N_VAL_SHIFT 16
-#define BYT_PRV_CLK_UPDATE (1 << 31)
-
-#define BYT_TX_OVF_INT 0x820
-#define BYT_TX_OVF_INT_MASK (1 << 1)
-
-static void
-byt_set_termios(struct uart_port *p, struct ktermios *termios,
- struct ktermios *old)
-{
- unsigned int baud = tty_termios_baud_rate(termios);
- unsigned long fref = 100000000, fuart = baud * 16;
- unsigned long w = BIT(15) - 1;
- unsigned long m, n;
- u32 reg;
-
- /* Gracefully handle the B0 case: fall back to B9600 */
- fuart = fuart ? fuart : 9600 * 16;
-
- /* Get Fuart closer to Fref */
- fuart *= rounddown_pow_of_two(fref / fuart);
-
- /*
- * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
- * dividers must be adjusted.
- *
- * uartclk = (m / n) * 100 MHz, where m <= n
- */
- rational_best_approximation(fuart, fref, w, w, &m, &n);
- p->uartclk = fuart;
-
- /* Reset the clock */
- reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
- writel(reg, p->membase + BYT_PRV_CLK);
- reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
- writel(reg, p->membase + BYT_PRV_CLK);
-
- p->status &= ~UPSTAT_AUTOCTS;
- if (termios->c_cflag & CRTSCTS)
- p->status |= UPSTAT_AUTOCTS;
-
- serial8250_do_set_termios(p, termios, old);
-}
-
-static bool byt_dma_filter(struct dma_chan *chan, void *param)
-{
- struct dw_dma_slave *dws = param;
-
- if (dws->dma_dev != chan->device->dev)
- return false;
-
- chan->private = dws;
- return true;
-}
-
-static unsigned int
-byt_get_mctrl(struct uart_port *port)
-{
- unsigned int ret = serial8250_do_get_mctrl(port);
-
- /* Force DCD and DSR signals to permanently be reported as active. */
- ret |= TIOCM_CAR | TIOCM_DSR;
-
- return ret;
-}
-
-static int
-byt_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
-{
- struct pci_dev *pdev = priv->dev;
- struct device *dev = port->port.dev;
- struct uart_8250_dma *dma;
- struct dw_dma_slave *tx_param, *rx_param;
- struct pci_dev *dma_dev;
- int ret;
-
- dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
- if (!dma)
- return -ENOMEM;
-
- tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
- if (!tx_param)
- return -ENOMEM;
-
- rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
- if (!rx_param)
- return -ENOMEM;
-
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_BYT_UART1:
- case PCI_DEVICE_ID_INTEL_BSW_UART1:
- case PCI_DEVICE_ID_INTEL_BDW_UART1:
- rx_param->src_id = 3;
- tx_param->dst_id = 2;
- break;
- case PCI_DEVICE_ID_INTEL_BYT_UART2:
- case PCI_DEVICE_ID_INTEL_BSW_UART2:
- case PCI_DEVICE_ID_INTEL_BDW_UART2:
- rx_param->src_id = 5;
- tx_param->dst_id = 4;
- break;
- default:
- return -EINVAL;
- }
-
- rx_param->m_master = 0;
- rx_param->p_master = 1;
-
- dma->rxconf.src_maxburst = 16;
-
- tx_param->m_master = 0;
- tx_param->p_master = 1;
-
- dma->txconf.dst_maxburst = 16;
-
- dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
- rx_param->dma_dev = &dma_dev->dev;
- tx_param->dma_dev = &dma_dev->dev;
-
- dma->fn = byt_dma_filter;
- dma->rx_param = rx_param;
- dma->tx_param = tx_param;
-
- ret = pci_default_setup(priv, board, port, idx);
- port->port.iotype = UPIO_MEM;
- port->port.type = PORT_16550A;
- port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
- port->port.set_termios = byt_set_termios;
- port->port.get_mctrl = byt_get_mctrl;
- port->port.fifosize = 64;
- port->tx_loadsz = 64;
- port->dma = dma;
- port->capabilities = UART_CAP_FIFO | UART_CAP_AFE;
-
- /* Disable Tx counter interrupts */
- writel(BYT_TX_OVF_INT_MASK, port->port.membase + BYT_TX_OVF_INT);
-
- return ret;
-}
-
 static int
 pci_omegapci_setup(struct serial_private *priv,
       const struct pciserial_board *board,
@@ -2030,48 +1872,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
  .subdevice = PCI_ANY_ID,
  .setup = kt_serial_setup,
  },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_BYT_UART1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = byt_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_BYT_UART2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = byt_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_BSW_UART1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = byt_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_BSW_UART2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = byt_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_BDW_UART1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = byt_serial_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_BDW_UART2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = byt_serial_setup,
- },
  /*
  * ITE
  */
@@ -2936,7 +2736,6 @@ enum pci_board_num_t {
  pbn_ADDIDATA_PCIe_4_3906250,
  pbn_ADDIDATA_PCIe_8_3906250,
  pbn_ce4100_1_115200,
- pbn_byt,
  pbn_qrk,
  pbn_omegapci,
  pbn_NETMOS9900_2s_115200,
@@ -3713,12 +3512,6 @@ static struct pciserial_board pci_boards[] = {
  .base_baud = 921600,
  .reg_shift      = 2,
  },
- [pbn_byt] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 2764800,
- .reg_shift      = 2,
- },
  [pbn_qrk] = {
  .flags = FL_BASE0,
  .num_ports = 1,
@@ -3835,6 +3628,14 @@ static const struct pci_device_id blacklist[] = {
  { PCI_VDEVICE(INTEL, 0x081d), },
  { PCI_VDEVICE(INTEL, 0x1191), },
  { PCI_VDEVICE(INTEL, 0x19d8), },
+
+ /* Intel platforms with DesignWare UART */
+ { PCI_VDEVICE(INTEL, 0x0f0a), },
+ { PCI_VDEVICE(INTEL, 0x0f0c), },
+ { PCI_VDEVICE(INTEL, 0x228a), },
+ { PCI_VDEVICE(INTEL, 0x228c), },
+ { PCI_VDEVICE(INTEL, 0x9ce3), },
+ { PCI_VDEVICE(INTEL, 0x9ce4), },
 };
 
 /*
@@ -5500,33 +5301,6 @@ static struct pci_device_id serial_pci_tbl[] = {
  { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
  PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
  pbn_ce4100_1_115200 },
- /* Intel BayTrail */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1,
- PCI_ANY_ID,  PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
- pbn_byt },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2,
- PCI_ANY_ID,  PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
- pbn_byt },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW_UART1,
- PCI_ANY_ID,  PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
- pbn_byt },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW_UART2,
- PCI_ANY_ID,  PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
- pbn_byt },
-
- /* Intel Broadwell */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART1,
- PCI_ANY_ID,  PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
- pbn_byt },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART2,
- PCI_ANY_ID,  PCI_ANY_ID,
- PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
- pbn_byt },
 
  /*
  * Intel Quark x1000
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index e46761d..613e512 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -120,7 +120,6 @@ config SERIAL_8250_PCI
  tristate "8250/16550 PCI device support" if EXPERT
  depends on SERIAL_8250 && PCI
  default SERIAL_8250
- select RATIONAL
  help
   This builds standard PCI serial support. You may be able to
   disable this feature if you only need legacy serial support.
@@ -401,6 +400,21 @@ config SERIAL_8250_INGENIC
   If you have a system using an Ingenic SoC and wish to make use of
   its UARTs, say Y to this option. If unsure, say N.
 
+config SERIAL_8250_LPSS
+ tristate "Support for serial ports on Intel LPSS platforms" if EXPERT
+ default SERIAL_8250
+ depends on SERIAL_8250 && PCI
+ depends on X86 || COMPILE_TEST
+ select DW_DMAC_CORE if SERIAL_8250_DMA
+ select DW_DMAC_PCI if (SERIAL_8250_DMA && X86_INTEL_LPSS)
+ select RATIONAL
+ help
+  Selecting this option will enable handling of the extra features
+  present on the UART found on various Intel platforms such as:
+    - Intel Baytrail SoC
+    - Intel Braswell SoC
+    - Intel Quark X1000 SoC
+
 config SERIAL_8250_MID
  tristate "Support for serial ports on Intel MID platforms" if EXPERT
  default SERIAL_8250
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 367d403..276c6fb 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o
 obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
 obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
 obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
+obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
 obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
 obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 02/11] dmaengine: dw: provide probe(), remove() stubs for users

Andy Shevchenko
In reply to this post by Andy Shevchenko
Some users consider DMA optional, thus when driver is not compiled we shouldn't
prevent compilation of the users. Add stubs for dw_dma_probe() and
dw_dma_remove().

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 include/linux/dma/dw.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/dma/dw.h b/include/linux/dma/dw.h
index f2e538a..ccfd0c3 100644
--- a/include/linux/dma/dw.h
+++ b/include/linux/dma/dw.h
@@ -40,8 +40,13 @@ struct dw_dma_chip {
 };
 
 /* Export to the platform drivers */
+#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
 int dw_dma_probe(struct dw_dma_chip *chip);
 int dw_dma_remove(struct dw_dma_chip *chip);
+#else
+static inline int dw_dma_probe(struct dw_dma_chip *chip) { return -ENODEV; }
+static inline int dw_dma_remove(struct dw_dma_chip *chip) { return 0; }
+#endif /* CONFIG_DW_DMAC_CORE */
 
 /* DMA API extensions */
 struct dw_desc;
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 03/11] dmaengine: dw: set polarity of handshake interface

Andy Shevchenko
In reply to this post by Andy Shevchenko
Intel Quark UART uses DesignWare DMA IP. Though the DMA IP is connected in such
way that handshake interface uses inverted polarity. We have to provide a
possibility to set this in the DMA driver when configuring a channel.

Introduce a new member of custom slave configuration called 'polarity' and set
active low polarity in case this value is 'true'.

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/dma/dw/core.c                | 4 ++++
 include/linux/platform_data/dma-dw.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index 81b06df..59f571c 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -150,6 +150,10 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
  cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id);
  cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id);
 
+ /* Set polarity of handshake interface */
+ cfglo |= dwc->dws.hs_polarity ?
+ DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0;
+
  channel_writel(dwc, CFG_LO, cfglo);
  channel_writel(dwc, CFG_HI, cfghi);
 
diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h
index d15d8ba..4636c93 100644
--- a/include/linux/platform_data/dma-dw.h
+++ b/include/linux/platform_data/dma-dw.h
@@ -23,6 +23,7 @@
  * @dst_id: dst request line
  * @m_master: memory master for transfers on allocated channel
  * @p_master: peripheral master for transfers on allocated channel
+ * @hs_polarity:set active low polarity of handshake interface
  */
 struct dw_dma_slave {
  struct device *dma_dev;
@@ -30,6 +31,7 @@ struct dw_dma_slave {
  u8 dst_id;
  u8 m_master;
  u8 p_master;
+ bool hs_polarity;
 };
 
 /**
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 11/11] serial: 8250_lpss: enable DMA on Intel Quark UART

Andy Shevchenko
In reply to this post by Andy Shevchenko
DMA on Intel Quark SoC is a part of UART IP block. Enable it.

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250_lpss.c | 61 +++++++++++++++++++++++++++++++++++--
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index c83fd51..0f4134a 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -15,7 +15,7 @@
 #include <linux/rational.h>
 
 #include <linux/dmaengine.h>
-#include <linux/platform_data/dma-dw.h>
+#include <linux/dma/dw.h>
 
 #include "8250.h"
 
@@ -47,6 +47,7 @@ struct lpss8250_board {
  unsigned long freq;
  unsigned int base_baud;
  int (*setup)(struct lpss8250 *, struct uart_port *p);
+ void (*exit)(struct lpss8250 *);
 };
 
 struct lpss8250 {
@@ -55,6 +56,7 @@ struct lpss8250 {
 
  /* DMA parameters */
  struct uart_8250_dma dma;
+ struct dw_dma_chip dma_chip;
  struct dw_dma_slave dma_param;
  u8 dma_maxburst;
 };
@@ -150,17 +152,61 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
  return 0;
 }
 
+static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
+ .nr_channels = 2,
+ .is_private = true,
+ .is_nollp = true,
+ .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .block_size = 4095,
+ .nr_masters = 1,
+ .data_width = {4},
+};
+
 static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
 {
+ struct uart_8250_dma *dma = &lpss->dma;
+ struct dw_dma_chip *chip = &lpss->dma_chip;
+ struct dw_dma_slave *param = &lpss->dma_param;
  struct pci_dev *pdev = to_pci_dev(port->dev);
+ int ret;
 
  pci_enable_msi(pdev);
 
  port->irq = pdev->irq;
 
+ chip->dev = &pdev->dev;
+ chip->irq = pdev->irq;
+ chip->regs = pci_ioremap_bar(pdev, 1);
+ chip->pdata = &qrk_serial_dma_pdata;
+
+ /* Falling back to PIO mode if DMA probing fails */
+ ret = dw_dma_probe(chip);
+ if (ret)
+ return 0;
+
+ /* Special DMA address for UART */
+ dma->rx_dma_addr = 0xfffff000;
+ dma->tx_dma_addr = 0xfffff000;
+
+ param->dma_dev = &pdev->dev;
+ param->src_id = 0;
+ param->dst_id = 1;
+ param->hs_polarity = true;
+
+ lpss->dma_maxburst = 8;
  return 0;
 }
 
+static void qrk_serial_exit(struct lpss8250 *lpss)
+{
+ struct dw_dma_slave *param = &lpss->dma_param;
+
+ if (!param->dma_dev)
+ return;
+ dw_dma_remove(&lpss->dma_chip);
+}
+
 static bool lpss8250_dma_filter(struct dma_chan *chan, void *param)
 {
  struct dw_dma_slave *dws = param;
@@ -243,22 +289,30 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
  ret = lpss8250_dma_setup(lpss, &uart);
  if (ret)
- return ret;
+ goto err_exit;
 
  ret = serial8250_register_8250_port(&uart);
  if (ret < 0)
- return ret;
+ goto err_exit;
 
  lpss->line = ret;
 
  pci_set_drvdata(pdev, lpss);
  return 0;
+
+err_exit:
+ if (lpss->board->exit)
+ lpss->board->exit(lpss);
+ return ret;
 }
 
 static void lpss8250_remove(struct pci_dev *pdev)
 {
  struct lpss8250 *lpss = pci_get_drvdata(pdev);
 
+ if (lpss->board->exit)
+ lpss->board->exit(lpss);
+
  serial8250_unregister_port(lpss->line);
 }
 
@@ -272,6 +326,7 @@ static const struct lpss8250_board qrk_board = {
  .freq = 44236800,
  .base_baud = 2764800,
  .setup = qrk_serial_setup,
+ .exit = qrk_serial_exit,
 };
 
 #define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 05/11] serial: 8250_dma: switch to new dmaengine_terminate_* API

Andy Shevchenko
In reply to this post by Andy Shevchenko
Convert dmaengine_terminate_all() calls to synchronous and asynchronous
versions where appropriate.

Reviewed-by: Peter Hurley <[hidden email]>
Reviewed-by: Heikki Krogerus <[hidden email]>
Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250_dma.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 445895f..75c4b40 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -142,7 +142,7 @@ void serial8250_rx_dma_flush(struct uart_8250_port *p)
  if (dma->rx_running) {
  dmaengine_pause(dma->rxchan);
  __dma_rx_complete(p);
- dmaengine_terminate_all(dma->rxchan);
+ dmaengine_terminate_async(dma->rxchan);
  }
 }
 
@@ -246,14 +246,14 @@ void serial8250_release_dma(struct uart_8250_port *p)
  return;
 
  /* Release RX resources */
- dmaengine_terminate_all(dma->rxchan);
+ dmaengine_terminate_sync(dma->rxchan);
  dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf,
   dma->rx_addr);
  dma_release_channel(dma->rxchan);
  dma->rxchan = NULL;
 
  /* Release TX resources */
- dmaengine_terminate_all(dma->txchan);
+ dmaengine_terminate_sync(dma->txchan);
  dma_unmap_single(dma->txchan->device->dev, dma->tx_addr,
  UART_XMIT_SIZE, DMA_TO_DEVICE);
  dma_release_channel(dma->txchan);
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 07/11] serial: 8250: enable AFE on ports where FIFO is 16 bytes

Andy Shevchenko
In reply to this post by Andy Shevchenko
Intel Quark has 16550A compatible UART with autoflow feature enabled. It has
only 16 bytes of FIFO. Currently serial8250_do_set_termios() prevents to enable
autoflow since the minimum requirement of 32 bytes of FIFO size.

Drop a FIFO size limitation to allow autoflow control be enabled on such UARTs.

While here, comment out UART_CAP_AFE for PORT_AR7 since it wasn't working and
it will be not a good idea to use it in conjunction with trigger level of 1
byte.

Suggested-by: Peter Hurley <[hidden email]>
Reviewed-by: Peter Hurley <[hidden email]>
Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250_port.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index d403603..be9cc37 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -178,7 +178,7 @@ static const struct serial8250_config uart_config[] = {
  .fifo_size = 16,
  .tx_loadsz = 16,
  .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ .flags = UART_CAP_FIFO /* | UART_CAP_AFE */,
  },
  [PORT_U6_16550A] = {
  .name = "U6_16550A",
@@ -2550,12 +2550,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
  /*
  * MCR-based auto flow control.  When AFE is enabled, RTS will be
  * deasserted when the receive FIFO contains more characters than
- * the trigger, or the MCR RTS bit is cleared.  In the case where
- * the remote UART is not using CTS auto flow control, we must
- * have sufficient FIFO entries for the latency of the remote
- * UART to respond.  IOW, at least 32 bytes of FIFO.
+ * the trigger, or the MCR RTS bit is cleared.
  */
- if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
+ if (up->capabilities & UART_CAP_AFE) {
  up->mcr &= ~UART_MCR_AFE;
  if (termios->c_cflag & CRTSCTS)
  up->mcr |= UART_MCR_AFE;
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 09/11] serial: 8250_lpss: move Quark code from PCI driver

Andy Shevchenko
In reply to this post by Andy Shevchenko
Intel Quark has DesignWare UART. Move the code from 8250_pci to 8250_lpss.

Reviewed-by: Bryan O'Donoghue <[hidden email]>
Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250_lpss.c | 11 +++++++++++
 drivers/tty/serial/8250/8250_pci.c  | 15 +--------------
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 77cf7e3..3beb3aa 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -25,6 +25,8 @@
 #define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
 #define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
 
+#define PCI_DEVICE_ID_INTEL_QRK_UARTx 0x0936
+
 #define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
 #define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
 
@@ -165,6 +167,9 @@ static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port
  struct dw_dma_slave *rx_param, *tx_param;
  struct device *dev = port->port.dev;
 
+ if (!lpss->dma_param.dma_dev)
+ return 0;
+
  rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
  if (!rx_param)
  return -ENOMEM;
@@ -252,6 +257,11 @@ static const struct lpss8250_board byt_board = {
  .setup = byt_serial_setup,
 };
 
+static const struct lpss8250_board qrk_board = {
+ .freq = 44236800,
+ .base_baud = 2764800,
+};
+
 #define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
 
 static const struct pci_device_id pci_ids[] = {
@@ -259,6 +269,7 @@ static const struct pci_device_id pci_ids[] = {
  LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART2, byt_board),
  LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART1, byt_board),
  LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART2, byt_board),
+ LPSS_DEVICE(PCI_DEVICE_ID_INTEL_QRK_UARTx, qrk_board),
  LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART1, byt_board),
  LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART2, byt_board),
  { },
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index bb4df5d..b94b1ee 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1765,7 +1765,6 @@ pci_wch_ch38x_setup(struct serial_private *priv,
 #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
-#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936
 
 #define PCI_VENDOR_ID_SUNIX 0x1fd4
 #define PCI_DEVICE_ID_SUNIX_1999 0x1999
@@ -2736,7 +2735,6 @@ enum pci_board_num_t {
  pbn_ADDIDATA_PCIe_4_3906250,
  pbn_ADDIDATA_PCIe_8_3906250,
  pbn_ce4100_1_115200,
- pbn_qrk,
  pbn_omegapci,
  pbn_NETMOS9900_2s_115200,
  pbn_brcm_trumanage,
@@ -3512,12 +3510,6 @@ static struct pciserial_board pci_boards[] = {
  .base_baud = 921600,
  .reg_shift      = 2,
  },
- [pbn_qrk] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 2764800,
- .reg_shift = 2,
- },
  [pbn_omegapci] = {
  .flags = FL_BASE0,
  .num_ports = 8,
@@ -3634,6 +3626,7 @@ static const struct pci_device_id blacklist[] = {
  { PCI_VDEVICE(INTEL, 0x0f0c), },
  { PCI_VDEVICE(INTEL, 0x228a), },
  { PCI_VDEVICE(INTEL, 0x228c), },
+ { PCI_VDEVICE(INTEL, 0x0936), },
  { PCI_VDEVICE(INTEL, 0x9ce3), },
  { PCI_VDEVICE(INTEL, 0x9ce4), },
 };
@@ -5303,12 +5296,6 @@ static struct pci_device_id serial_pci_tbl[] = {
  pbn_ce4100_1_115200 },
 
  /*
- * Intel Quark x1000
- */
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_qrk },
- /*
  * Cronyx Omega PCI
  */
  { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 06/11] serial: 8250_dma: adjust DMA address of the UART

Andy Shevchenko
In reply to this post by Andy Shevchenko
Some UARTs, e.g. one is used in Intel Quark, have a different address base for
DMA operations. Introduce an additional field (per RX and TX DMA channels) in
struct uart_8250_dma to cover those cases.

Reviewed-by: Heikki Krogerus <[hidden email]>
Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/tty/serial/8250/8250.h     | 5 +++++
 drivers/tty/serial/8250/8250_dma.c | 8 ++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 215a992..664232b 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -31,6 +31,11 @@ struct uart_8250_dma {
  struct dma_chan *rxchan;
  struct dma_chan *txchan;
 
+ /* Device address base for DMA operations */
+ phys_addr_t rx_dma_addr;
+ phys_addr_t tx_dma_addr;
+
+ /* DMA address of the buffer in memory */
  dma_addr_t rx_addr;
  dma_addr_t tx_addr;
 
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 75c4b40..2db57b0 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -149,6 +149,10 @@ void serial8250_rx_dma_flush(struct uart_8250_port *p)
 int serial8250_request_dma(struct uart_8250_port *p)
 {
  struct uart_8250_dma *dma = p->dma;
+ phys_addr_t rx_dma_addr = dma->rx_dma_addr ?
+  dma->rx_dma_addr : p->port.mapbase;
+ phys_addr_t tx_dma_addr = dma->tx_dma_addr ?
+  dma->tx_dma_addr : p->port.mapbase;
  dma_cap_mask_t mask;
  struct dma_slave_caps caps;
  int ret;
@@ -156,11 +160,11 @@ int serial8250_request_dma(struct uart_8250_port *p)
  /* Default slave configuration parameters */
  dma->rxconf.direction = DMA_DEV_TO_MEM;
  dma->rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- dma->rxconf.src_addr = p->port.mapbase + UART_RX;
+ dma->rxconf.src_addr = rx_dma_addr + UART_RX;
 
  dma->txconf.direction = DMA_MEM_TO_DEV;
  dma->txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- dma->txconf.dst_addr = p->port.mapbase + UART_TX;
+ dma->txconf.dst_addr = tx_dma_addr + UART_TX;
 
  dma_cap_zero(mask);
  dma_cap_set(DMA_SLAVE, mask);
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 01/11] dmaengine: dw: keep copy of custom slave config in dwc

Andy Shevchenko
In reply to this post by Andy Shevchenko
It seems we need to extend custom slave configuration by one more member to
support Intel Quart UART. It becomes a burden to manage all members of struct
dw_dma_slave one-by-one.

Replace set of fields by embedding struct dw_dma_slave into struct dw_dma_chan.

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/dma/dw/core.c | 29 ++++++++++-------------------
 drivers/dma/dw/regs.h |  5 +----
 2 files changed, 11 insertions(+), 23 deletions(-)

diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index edf053f..81b06df 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -46,9 +46,9 @@
  u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \
  DW_DMA_MSIZE_16; \
  u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ? \
- _dwc->p_master : _dwc->m_master; \
+ _dwc->dws.p_master : _dwc->dws.m_master; \
  u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ? \
- _dwc->p_master : _dwc->m_master; \
+ _dwc->dws.p_master : _dwc->dws.m_master; \
  \
  (DWC_CTLL_DST_MSIZE(_dmsize) \
  | DWC_CTLL_SRC_MSIZE(_smsize) \
@@ -147,8 +147,8 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
  if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
  return;
 
- cfghi |= DWC_CFGH_DST_PER(dwc->dst_id);
- cfghi |= DWC_CFGH_SRC_PER(dwc->src_id);
+ cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id);
+ cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id);
 
  channel_writel(dwc, CFG_LO, cfglo);
  channel_writel(dwc, CFG_HI, cfghi);
@@ -209,7 +209,7 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc,
 static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
 {
  struct dw_dma *dw = to_dw_dma(dwc->chan.device);
- u8 lms = DWC_LLP_LMS(dwc->m_master);
+ u8 lms = DWC_LLP_LMS(dwc->dws.m_master);
  unsigned long was_soft_llp;
 
  /* ASSERT:  channel is idle */
@@ -662,7 +662,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
  struct dw_desc *prev;
  size_t xfer_count;
  size_t offset;
- u8 m_master = dwc->m_master;
+ u8 m_master = dwc->dws.m_master;
  unsigned int src_width;
  unsigned int dst_width;
  unsigned int data_width = dw->pdata->data_width[m_master];
@@ -740,7 +740,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
  struct dw_desc *prev;
  struct dw_desc *first;
  u32 ctllo;
- u8 m_master = dwc->m_master;
+ u8 m_master = dwc->dws.m_master;
  u8 lms = DWC_LLP_LMS(m_master);
  dma_addr_t reg;
  unsigned int reg_width;
@@ -895,12 +895,7 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
  return false;
 
  /* We have to copy data since dws can be temporary storage */
-
- dwc->src_id = dws->src_id;
- dwc->dst_id = dws->dst_id;
-
- dwc->m_master = dws->m_master;
- dwc->p_master = dws->p_master;
+ memcpy(&dwc->dws, dws, sizeof(struct dw_dma_slave));
 
  return true;
 }
@@ -1167,11 +1162,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
  spin_lock_irqsave(&dwc->lock, flags);
 
  /* Clear custom channel configuration */
- dwc->src_id = 0;
- dwc->dst_id = 0;
-
- dwc->m_master = 0;
- dwc->p_master = 0;
+ memset(&dwc->dws, 0, sizeof(struct dw_dma_slave));
 
  clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
 
@@ -1264,7 +1255,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
  struct dw_cyclic_desc *retval = NULL;
  struct dw_desc *desc;
  struct dw_desc *last = NULL;
- u8 lms = DWC_LLP_LMS(dwc->m_master);
+ u8 lms = DWC_LLP_LMS(dwc->dws.m_master);
  unsigned long was_cyclic;
  unsigned int reg_width;
  unsigned int periods;
diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h
index 4b7bd78..f65dd10 100644
--- a/drivers/dma/dw/regs.h
+++ b/drivers/dma/dw/regs.h
@@ -245,10 +245,7 @@ struct dw_dma_chan {
  bool nollp;
 
  /* custom slave configuration */
- u8 src_id;
- u8 dst_id;
- u8 m_master;
- u8 p_master;
+ struct dw_dma_slave dws;
 
  /* configuration passed via .device_config */
  struct dma_slave_config dma_sconfig;
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH v5 04/11] dmaengine: dw: override LLP support if asked in platform data

Andy Shevchenko
In reply to this post by Andy Shevchenko
There is at least one known device, i.e. UART on Intel Galileo, that works
unreliably in case of use of multi block transfer support in DMA mode.

Override autodetection by user provided data.

Signed-off-by: Andy Shevchenko <[hidden email]>
---
 drivers/dma/dw/core.c                | 10 +++++++---
 include/linux/platform_data/dma-dw.h |  2 ++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index 59f571c..d2d1d51 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -1573,9 +1573,13 @@ int dw_dma_probe(struct dw_dma_chip *chip)
  dwc->block_size = pdata->block_size;
 
  /* Check if channel supports multi block transfer */
- channel_writel(dwc, LLP, DWC_LLP_LOC(0xffffffff));
- dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0;
- channel_writel(dwc, LLP, 0);
+ if (pdata->is_nollp) {
+ dwc->nollp = pdata->is_nollp;
+ } else {
+ channel_writel(dwc, LLP, DWC_LLP_LOC(0xffffffff));
+ dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0;
+ channel_writel(dwc, LLP, 0);
+ }
  }
  }
 
diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h
index 4636c93..5f0e11e 100644
--- a/include/linux/platform_data/dma-dw.h
+++ b/include/linux/platform_data/dma-dw.h
@@ -40,6 +40,7 @@ struct dw_dma_slave {
  * @is_private: The device channels should be marked as private and not for
  * by the general purpose DMA channel allocator.
  * @is_memcpy: The device channels do support memory-to-memory transfers.
+ * @is_nollp: The device channels does not support multi block transfers.
  * @chan_allocation_order: Allocate channels starting from 0 or 7
  * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
  * @block_size: Maximum block size supported by the controller
@@ -51,6 +52,7 @@ struct dw_dma_platform_data {
  unsigned int nr_channels;
  bool is_private;
  bool is_memcpy;
+ bool is_nollp;
 #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */
 #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */
  unsigned char chan_allocation_order;
--
2.8.1

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Andy Shevchenko
In reply to this post by Andy Shevchenko
On Fri, 2016-05-06 at 18:17 +0300, Andy Shevchenko wrote:

> This is combined series of two things:
> - split out the Intel LPSS specific driver from 8250_pci into
> 8250_lpss
> - enable DMA support on Intel Quark UART
>
> The patch has been tested on few Intel SoCs / platforms. In any case I
> would
> like to ask Bryan to do independent test.
>
> This is targeting serial subsystem, thus it would be nice to get and
> Ack from
> Vinod first. Moreover, the series depends on [1] that is now in
> Vinod's
> slave-dma tree.
>
> That's why I asked Vinod to create immutable tag / branch for the [1]
> and the
> dependants (at least one more, which is sata_dwc_460ex) can use it.
>
> The series can be reached in the branch located at [2].
>
> [1] http://www.spinics.net/lists/kernel/msg2244475.html
> [2] https://bitbucket.org/andy-shev/linux/branch/topic%2Fdw%2Fqrk
>

Do we have a chance to get this? Requirement, i.e. topic/dw branch of
Vinod's slave-dma tree is available and has all prerequisites.

> Since v4:
> - fix an issue what kernel test bot reported (lkp)
> - add a list of supported SoC to Kconfig (Bryan)
> - rename polarity -> hs_polarity (Bryan)
>
> Since v3:
> - rebase on top of recent tty-next branch
> - add Reviewed-by tag from Bryan
>
> Since v2:
> - add tags
> - rebase on top of new version of [1]
>
> Since v1:
> - address most of Peter's comments (mostly changelog to patch 8)
> - add tag to patch 5
> - drop patch 6 from the series to be separately dealt with
>
> Andy Shevchenko (11):
>   dmaengine: dw: keep copy of custom slave config in dwc
>   dmaengine: dw: provide probe(), remove() stubs for users
>   dmaengine: dw: set polarity of handshake interface
>   dmaengine: dw: override LLP support if asked in platform data
>   serial: 8250_dma: switch to new dmaengine_terminate_* API
>   serial: 8250_dma: adjust DMA address of the UART
>   serial: 8250: enable AFE on ports where FIFO is 16 bytes
>   serial: 8250_lpss: split LPSS driver to separate module
>   serial: 8250_lpss: move Quark code from PCI driver
>   serial: 8250_lpss: enable MSI for Intel Quark
>   serial: 8250_lpss: enable DMA on Intel Quark UART
>
>  drivers/dma/dw/core.c                |  43 +++--
>  drivers/dma/dw/regs.h                |   5 +-
>  drivers/tty/serial/8250/8250.h       |   5 +
>  drivers/tty/serial/8250/8250_dma.c   |  14 +-
>  drivers/tty/serial/8250/8250_lpss.c  | 357
> +++++++++++++++++++++++++++++++++++
>  drivers/tty/serial/8250/8250_pci.c   | 257 +------------------------
>  drivers/tty/serial/8250/8250_port.c  |   9 +-
>  drivers/tty/serial/8250/Kconfig      |  16 +-
>  drivers/tty/serial/8250/Makefile     |   1 +
>  include/linux/dma/dw.h               |   5 +
>  include/linux/platform_data/dma-dw.h |   4 +
>  11 files changed, 430 insertions(+), 286 deletions(-)
>  create mode 100644 drivers/tty/serial/8250/8250_lpss.c
>

--
Andy Shevchenko <[hidden email]>
Intel Finland Oy

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Vinod Koul-3
On Thu, May 12, 2016 at 06:06:41PM +0300, Andy Shevchenko wrote:

> On Fri, 2016-05-06 at 18:17 +0300, Andy Shevchenko wrote:
> > This is combined series of two things:
> > - split out the Intel LPSS specific driver from 8250_pci into
> > 8250_lpss
> > - enable DMA support on Intel Quark UART
> >
> > The patch has been tested on few Intel SoCs / platforms. In any case I
> > would
> > like to ask Bryan to do independent test.
> >
> > This is targeting serial subsystem, thus it would be nice to get and
> > Ack from
> > Vinod first. Moreover, the series depends on [1] that is now in
> > Vinod's
> > slave-dma tree.
> >
> > That's why I asked Vinod to create immutable tag / branch for the [1]
> > and the
> > dependants (at least one more, which is sata_dwc_460ex) can use it.
> >
> > The series can be reached in the branch located at [2].
> >
> > [1] http://www.spinics.net/lists/kernel/msg2244475.html
> > [2] https://bitbucket.org/andy-shev/linux/branch/topic%2Fdw%2Fqrk
> >
>
> Do we have a chance to get this? Requirement, i.e. topic/dw branch of
> Vinod's slave-dma tree is available and has all prerequisites.

All dmaengine patches

Acked-by: Vinod Koul <[hidden email]>

Thanks
--
~Vinod

>
> > Since v4:
> > - fix an issue what kernel test bot reported (lkp)
> > - add a list of supported SoC to Kconfig (Bryan)
> > - rename polarity -> hs_polarity (Bryan)
> >
> > Since v3:
> > - rebase on top of recent tty-next branch
> > - add Reviewed-by tag from Bryan
> >
> > Since v2:
> > - add tags
> > - rebase on top of new version of [1]
> >
> > Since v1:
> > - address most of Peter's comments (mostly changelog to patch 8)
> > - add tag to patch 5
> > - drop patch 6 from the series to be separately dealt with
> >
> > Andy Shevchenko (11):
> >   dmaengine: dw: keep copy of custom slave config in dwc
> >   dmaengine: dw: provide probe(), remove() stubs for users
> >   dmaengine: dw: set polarity of handshake interface
> >   dmaengine: dw: override LLP support if asked in platform data
> >   serial: 8250_dma: switch to new dmaengine_terminate_* API
> >   serial: 8250_dma: adjust DMA address of the UART
> >   serial: 8250: enable AFE on ports where FIFO is 16 bytes
> >   serial: 8250_lpss: split LPSS driver to separate module
> >   serial: 8250_lpss: move Quark code from PCI driver
> >   serial: 8250_lpss: enable MSI for Intel Quark
> >   serial: 8250_lpss: enable DMA on Intel Quark UART
> >
> >  drivers/dma/dw/core.c                |  43 +++--
> >  drivers/dma/dw/regs.h                |   5 +-
> >  drivers/tty/serial/8250/8250.h       |   5 +
> >  drivers/tty/serial/8250/8250_dma.c   |  14 +-
> >  drivers/tty/serial/8250/8250_lpss.c  | 357
> > +++++++++++++++++++++++++++++++++++
> >  drivers/tty/serial/8250/8250_pci.c   | 257 +------------------------
> >  drivers/tty/serial/8250/8250_port.c  |   9 +-
> >  drivers/tty/serial/8250/Kconfig      |  16 +-
> >  drivers/tty/serial/8250/Makefile     |   1 +
> >  include/linux/dma/dw.h               |   5 +
> >  include/linux/platform_data/dma-dw.h |   4 +
> >  11 files changed, 430 insertions(+), 286 deletions(-)
> >  create mode 100644 drivers/tty/serial/8250/8250_lpss.c
> >
>
> --
> Andy Shevchenko <[hidden email]>
> Intel Finland Oy
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Bryan O'Donoghue-3
In reply to this post by Andy Shevchenko
On Thu, 2016-05-12 at 18:06 +0300, Andy Shevchenko wrote:

> On Fri, 2016-05-06 at 18:17 +0300, Andy Shevchenko wrote:
> > This is combined series of two things:
> > - split out the Intel LPSS specific driver from 8250_pci into
> > 8250_lpss
> > - enable DMA support on Intel Quark UART
> >
> > The patch has been tested on few Intel SoCs / platforms. In any
> > case I
> > would
> > like to ask Bryan to do independent test.

Andy.

It looks as though there's a performance drop when enabling the DMA
here (v) stock PIO mode with the 8250 driver.

Test setup Galileo Gen1 transmitter - Galileo Gen2 receiver. TX/RX
cross-wired between the Arduino UART headers respectively (pins 0 & 1
on the "Digital PWM" header), GND pin14 similarly cross-wired.

User-space:
    Receiver: Stock on-flash yocto-tiny kernel 3.8.7
    Transmitter: Galileo Debian image :
                 https://sourceforge.net/projects/galileodebian/
    3.8.7 kernel: On SPI-flash BSP kernel
    andy-v4: From your tree
             d13ffcf ('serial: 8250: attempt to keep Kconfig and
                       Makefile in order')
    tip-of-tree : 97f0090 ('Merge tag 'rproc-v4.7' of
                            git://github.com/andersson/remoteproc')

Results:

### Test0 ###

galileo dma andy-v4 9600 8n1

root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
/dev/ttyS0

real    0m0.060s
user    0m0.000s
sys     0m0.000s


galileo non-dma Linux 3.8.7 9600 8n1:

9600 8n1
root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
/dev/ttyS0

real    0m0.051s
user    0m0.000s
sys     0m0.000s

galileo non-dma tip-of-tree 9600 8n1:

root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
/dev/ttyS0

real    0m0.048s
user    0m0.000s
sys     0m0.000s


### Test1 ###

galileo dma andy-v4 9600 8n1:

root@galileo:~# time echo
"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234567
89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456
789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0

real    0m0.209s
user    0m0.000s
sys     0m0.000s

galileo non-dma Linux 3.8.7 9600 8n1:

root@galileo:~# time echo
"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234567
89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456
789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0

real    0m0.206s
user    0m0.000s
sys     0m0.000s


galileo non-dma tip-of-tree 9600 8n1:

root@galileo:~# time echo
"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234567
89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456
789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0

real    0m0.199s
user    0m0.010s
sys     0m0.000s


---
bod
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Andy Shevchenko
On Thu, 2016-05-19 at 02:18 +0100, Bryan O'Donoghue wrote:

> On Thu, 2016-05-12 at 18:06 +0300, Andy Shevchenko wrote:
> > On Fri, 2016-05-06 at 18:17 +0300, Andy Shevchenko wrote:
> > > This is combined series of two things:
> > > - split out the Intel LPSS specific driver from 8250_pci into
> > > 8250_lpss
> > > - enable DMA support on Intel Quark UART
> > >
> > > The patch has been tested on few Intel SoCs / platforms. In any
> > > case I
> > > would
> > > like to ask Bryan to do independent test.
>
> Andy.
>
> It looks as though there's a performance drop when enabling the DMA
> here (v) stock PIO mode with the 8250 driver.

Below results doesn't show DMA case (by the way, how did you disable DMA
in 3.8.7?) for stock kernel.

Anyway, I added preliminary support to change DMA mode run-time. Check
my today topic/dw/qrk branch. It would be nice to see all 4 cases: DMA
vs non-DMA on stock kernel (Yocto) and mine.

P.S. What is the point to test arbitrary tip branch?

>
> Test setup Galileo Gen1 transmitter - Galileo Gen2 receiver. TX/RX
> cross-wired between the Arduino UART headers respectively (pins 0 & 1
> on the "Digital PWM" header), GND pin14 similarly cross-wired.
>
> User-space:
>     Receiver: Stock on-flash yocto-tiny kernel 3.8.7
>     Transmitter: Galileo Debian image :
>                  https://sourceforge.net/projects/galileodebian/
>     3.8.7 kernel: On SPI-flash BSP kernel
>     andy-v4: From your tree
>              d13ffcf ('serial: 8250: attempt to keep Kconfig and
>                        Makefile in order')
>     tip-of-tree : 97f0090 ('Merge tag 'rproc-v4.7' of
>                             git://github.com/andersson/remoteproc')
>
> Results:
>
> ### Test0 ###
>
> galileo dma andy-v4 9600 8n1 
>
> root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
> /dev/ttyS0
>
> real    0m0.060s
> user    0m0.000s
> sys     0m0.000s
>
>
> galileo non-dma Linux 3.8.7 9600 8n1:
>
> 9600 8n1
> root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
> /dev/ttyS0
>
> real    0m0.051s
> user    0m0.000s
> sys     0m0.000s
>
> galileo non-dma tip-of-tree 9600 8n1:
>
> root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
> /dev/ttyS0
>
> real    0m0.048s
> user    0m0.000s
> sys     0m0.000s
>
>
> ### Test1 ###
>
> galileo dma andy-v4 9600 8n1:
>
> root@galileo:~# time echo
> "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456
> 7
> 89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz012345
> 6
> 789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0
>
> real    0m0.209s
> user    0m0.000s
> sys     0m0.000s
>
> galileo non-dma Linux 3.8.7 9600 8n1:
>
> root@galileo:~# time echo
> "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456
> 7
> 89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz012345
> 6
> 789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0
>
> real    0m0.206s
> user    0m0.000s
> sys     0m0.000s
>
>
> galileo non-dma tip-of-tree 9600 8n1:
>
> root@galileo:~# time echo
> "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456
> 7
> 89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz012345
> 6
> 789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0
>
> real    0m0.199s
> user    0m0.010s
> sys     0m0.000s
>
>
> ---
> bod

--
Andy Shevchenko <[hidden email]>
Intel Finland Oy
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Andy Shevchenko
On Tue, 2016-05-24 at 20:37 +0300, Andy Shevchenko wrote:

> On Thu, 2016-05-19 at 02:18 +0100, Bryan O'Donoghue wrote:
> > On Thu, 2016-05-12 at 18:06 +0300, Andy Shevchenko wrote:
> > > On Fri, 2016-05-06 at 18:17 +0300, Andy Shevchenko wrote:
> > > > This is combined series of two things:
> > > > - split out the Intel LPSS specific driver from 8250_pci into
> > > > 8250_lpss
> > > > - enable DMA support on Intel Quark UART
> > > >
> > > > The patch has been tested on few Intel SoCs / platforms. In any
> > > > case I
> > > > would
> > > > like to ask Bryan to do independent test.
> >
> > Andy.
> >
> > It looks as though there's a performance drop when enabling the DMA
> > here (v) stock PIO mode with the 8250 driver.

Wait, the time measurement you done is unrelated to DMA/non-DMA mode.
It's significantly depend to the speed of the port.

It would be better to have 1000(s) of iterations to see any steady
difference out of statistical error. Below result doesn't show anything
like this.

I also tried on my Galileo board, I used longer data stream, i.e. output
of dmesg (since your data pattern makes 0:s in statistics) and got
something quite near to each other:

###
Size of the data (it actually become few dozens of bytes (55 bytes to be
precise) bigger since one message had been printed in the second part of
high speed test
###

% dmesg | wc -c
34965

### Low speed, DMA mode enabled by default ###
% stty -F /dev/ttyS0 9600

% time dmesg > /dev/ttyS0
real    0m 34.22s
user    0m 0.01s
sys     0m 0.02s

NOTE: Transfer speed: 34965b/34.22s ~= 1021.77b/s (9600 baud)

### non-DMA mode ###
% echo 3 > /sys/class/tty/ttyS0/dma_mode 

% time dmesg > /dev/ttyS0
real    0m 36.09s
user    0m 0.01s
sys     0m 0.02s

### Higher speed ###

% stty -F /dev/ttyS0 921600

% time dmesg > /dev/ttyS0
real    0m 0.41s
user    0m 0.01s
sys     0m 0.03s

NOTE: Transfer speed: 34965b/0.41s ~= 85280.49b/s (921600 baud)

### DMA mode enabled ###
% echo 0 > /sys/class/tty/ttyS0/dma_mode 

% time dmesg > /dev/ttyS0
real    0m 0.41s
user    0m 0.01s
sys     0m 0.02s

>
> Below results doesn't show DMA case (by the way, how did you disable
> DMA
> in 3.8.7?) for stock kernel.
>
> Anyway, I added preliminary support to change DMA mode run-time. Check
> my today topic/dw/qrk branch. It would be nice to see all 4 cases: DMA
> vs non-DMA on stock kernel (Yocto) and mine.
>
> P.S. What is the point to test arbitrary tip branch?
>
> >
> > Test setup Galileo Gen1 transmitter - Galileo Gen2 receiver. TX/RX
> > cross-wired between the Arduino UART headers respectively (pins 0 &
> > 1
> > on the "Digital PWM" header), GND pin14 similarly cross-wired.
> >
> > User-space:
> >     Receiver: Stock on-flash yocto-tiny kernel 3.8.7
> >     Transmitter: Galileo Debian image :
> >                  https://sourceforge.net/projects/galileodebian/
> >     3.8.7 kernel: On SPI-flash BSP kernel
> >     andy-v4: From your tree
> >              d13ffcf ('serial: 8250: attempt to keep Kconfig and
> >                        Makefile in order')
> >     tip-of-tree : 97f0090 ('Merge tag 'rproc-v4.7' of
> >                             git://github.com/andersson/remoteproc')
> >
> > Results:
> >
> > ### Test0 ###
> >
> > galileo dma andy-v4 9600 8n1 
> >
> > root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
> > /dev/ttyS0
> >
> > real    0m0.060s
> > user    0m0.000s
> > sys     0m0.000s
> >
> >
> > galileo non-dma Linux 3.8.7 9600 8n1:
> >
> > 9600 8n1
> > root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
> > /dev/ttyS0
> >
> > real    0m0.051s
> > user    0m0.000s
> > sys     0m0.000s
> >
> > galileo non-dma tip-of-tree 9600 8n1:
> >
> > root@galileo:~# time echo "abcdefghijklmnopqrstuvwxyz0123456789" >
> > /dev/ttyS0
> >
> > real    0m0.048s
> > user    0m0.000s
> > sys     0m0.000s
> >
> >
> > ### Test1 ###
> >
> > galileo dma andy-v4 9600 8n1:
> >
> > root@galileo:~# time echo
> > "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234
> > 56
> > 7
> > 89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123
> > 45
> > 6
> > 789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0
> >
> > real    0m0.209s
> > user    0m0.000s
> > sys     0m0.000s
> >
> > galileo non-dma Linux 3.8.7 9600 8n1:
> >
> > root@galileo:~# time echo
> > "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234
> > 56
> > 7
> > 89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123
> > 45
> > 6
> > 789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0
> >
> > real    0m0.206s
> > user    0m0.000s
> > sys     0m0.000s
> >
> >
> > galileo non-dma tip-of-tree 9600 8n1:
> >
> > root@galileo:~# time echo
> > "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234
> > 56
> > 7
> > 89abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123
> > 45
> > 6
> > 789abcdefghijklmnopqrstuvwxyz0123456789" > /dev/ttyS0
> >
> > real    0m0.199s
> > user    0m0.010s
> > sys     0m0.000s



--
Andy Shevchenko <[hidden email]>
Intel Finland Oy
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Bryan O'Donoghue-3
In reply to this post by Andy Shevchenko
On Tue, 2016-05-24 at 20:37 +0300, Andy Shevchenko wrote:
> Below results doesn't show DMA case (by the way, how did you disable
> DMA
> in 3.8.7?) for stock kernel.

The stock kernel on SPI flash for my early Gen1 is a non-DMA 8250
driver, so nothing needs to be done to that, it's basically just the
3.8.7 8250 in PIO mode.

> Anyway, I added preliminary support to change DMA mode run-time.
> Check
> my today topic/dw/qrk branch. It would be nice to see all 4 cases:
> DMA
> vs non-DMA on stock kernel (Yocto) and mine.

I'll have another look at your latest branch and run the same tests.

>
> P.S. What is the point to test arbitrary tip branch?

Just tip-of-tree, we can benchmark against the 4.6 tag if you prefer.


---
bod

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH v5 00/11] serial: 8250: split LPSS to 8250_lpss, enable DMA on Quark

Bryan O'Donoghue-3
In reply to this post by Andy Shevchenko
On Tue, 2016-05-24 at 21:08 +0300, Andy Shevchenko wrote:

> On Tue, 2016-05-24 at 20:37 +0300, Andy Shevchenko wrote:
> > On Thu, 2016-05-19 at 02:18 +0100, Bryan O'Donoghue wrote:
> > > On Thu, 2016-05-12 at 18:06 +0300, Andy Shevchenko wrote:
> > > > On Fri, 2016-05-06 at 18:17 +0300, Andy Shevchenko wrote:
> > > > > This is combined series of two things:
> > > > > - split out the Intel LPSS specific driver from 8250_pci into
> > > > > 8250_lpss
> > > > > - enable DMA support on Intel Quark UART
> > > > >
> > > > > The patch has been tested on few Intel SoCs / platforms. In
> > > > > any
> > > > > case I
> > > > > would
> > > > > like to ask Bryan to do independent test.
> > >
> > > Andy.
> > >
> > > It looks as though there's a performance drop when enabling the
> > > DMA
> > > here (v) stock PIO mode with the 8250 driver.
>
> Wait, the time measurement you done is unrelated to DMA/non-DMA mode.
> It's significantly depend to the speed of the port.

Does it ? The size of the FIFO is what - 16 bytes ? Max burst size is 8
bytes - so for 37 bytes you'd expect to see five DMA transactions {8,
8, 8, 5}, for the second test 183 bytes you'd expect to see 23 eight
byte transactions followed by one 7 byte transaction. The flip side to
add data to the FIFO in PIO mode is a pretty different pattern.

> I also tried on my Galileo board, I used longer data stream, i.e.
> output
> of dmesg (since your data pattern makes 0:s in statistics) and got
> something quite near to each other:

I'll find some time to look at both a short stream and a long stream,
based on the branch you've indicated and maybe against the latest
stable kernel.

---
bod
Loading...