linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/13 v10] omap 8250 based UART + DMA
@ 2014-09-29 18:06 Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 01/13] tty: serial: 8250: Fix wording in runtime-PM comments Sebastian Andrzej Siewior
                   ` (15 more replies)
  0 siblings, 16 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh

The queue is getting smaller. The highlights of v9…v10
- the DMA stall Frans Klaver reported which popped up in yocto is gone. It
  also seems that the "ack the err-irq even if nothing happened" in EDMA
  can be dropped.
- the RX- and TX-DMA callbacks are now OMAP-only and no "bugs" flags are
  introduced into the generic DMA code. This also means that there is
  custom IRQ routine in case of DMA.

Sebastian


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH 01/13] tty: serial: 8250: Fix wording in runtime-PM comments
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 02/13] tty: serial: 8250: make serial8250_console_setup() non _init Sebastian Andrzej Siewior
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

Frans reworded the two comments with better English for better
understanding. His review hit the mailing list after the patch got
applied so here is an incremental update.

Reported-by: Frans Klaver <frans.klaver@xsens.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 139f3d2b8aa9..a1904628a2a1 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -557,7 +557,7 @@ static void serial8250_rpm_put(struct uart_8250_port *p)
 }
 
 /*
- * This two wrapper ensure, that enable_runtime_pm_tx() can be called more than
+ * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
  * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
  * empty and the HW can idle again.
  */
@@ -1532,7 +1532,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
 	DEBUG_INTR("THRE...");
 
 	/*
-	 * With RPM enabled, we have to wait once the FIFO is empty before the
+	 * With RPM enabled, we have to wait until the FIFO is empty before the
 	 * HW can go idle. So we get here once again with empty FIFO and disable
 	 * the interrupt and RPM in __stop_tx()
 	 */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 02/13] tty: serial: 8250: make serial8250_console_setup() non _init
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 01/13] tty: serial: 8250: Fix wording in runtime-PM comments Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-30 20:27   ` Peter Hurley
  2014-09-29 18:06 ` [PATCH 03/13] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

if I boot with console=ttyS0 and the omap driver is module I end up with

| console [ttyS0] disabled
| omap8250 44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 88, base_baud = 3000000) is a 8250
| Unable to handle kernel paging request at virtual address c07a9de0
| Modules linked in: 8250_omap(+)
| CPU: 0 PID: 908 Comm: modprobe Not tainted 3.17.0-rc5+ #1593
| PC is at serial8250_console_setup+0x0/0xc8
| LR is at register_console+0x13c/0x3a4
| [<c0078788>] (register_console) from [<c02d0340>] (uart_add_one_port+0x3cc/0x420)
| [<c02d0340>] (uart_add_one_port) from [<c02d38a4>] (serial8250_register_8250_port+0x298/0x39c)
| [<c02d38a4>] (serial8250_register_8250_port) from [<bf006274>] (omap8250_probe+0x218/0x3dc [8250_omap])
| [<bf006274>] (omap8250_probe [8250_omap]) from [<c02e3424>] (platform_drv_probe+0x2c/0x5c)
| [<c02e3424>] (platform_drv_probe) from [<c02e1eac>] (driver_probe_device+0x104/0x228)
…
| [<c009fa48>] (SyS_init_module) from [<c000e6e0>] (ret_fast_syscall+0x0/0x30)
| Code: 7823603b f8314620 051b3013 491ed416 (44792204)

because serial8250_console_setup() is already gone.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index a1904628a2a1..159b72471622 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -3237,7 +3237,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
 	serial8250_rpm_put(up);
 }
 
-static int __init serial8250_console_setup(struct console *co, char *options)
+static int serial8250_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 03/13] tty: serial: Add 8250-core based omap driver
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 01/13] tty: serial: 8250: Fix wording in runtime-PM comments Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 02/13] tty: serial: 8250: make serial8250_console_setup() non _init Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 04/13] tty: serial: 8250_dma: handle error on TX submit Sebastian Andrzej Siewior
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

This patch provides a 8250-core based UART driver for the internal OMAP
UART. The long term goal is to provide the same functionality as the
current OMAP uart driver and DMA support.
I tried to merge omap-serial code together with the 8250-core code.
There should should be hardly a noticable difference. The trigger levels
are different compared to omap-serial:
- omap serial
  TX: Interrupt comes after TX FIFO has room for 16 bytes.
      TX of 4096 bytes in one go results in 256 interrupts

  RX: Interrupt comes after there is on byte in the FIFO.
      RX of 4096 bytes results in 4096 interrupts.

- this driver
  TX: Interrupt comes once the TX FIFO is empty.
      TX of 4096 bytes results in 65 interrupts. That means there will
      be gaps on the line while the driver reloads the FIFO.

  RX: Interrupt comes once there are 48 bytes in the FIFO or less over
      "longer" time frame. We have
          1 / 11520 * 10^3 * 16 => 1.38… ms
      1.38ms to react and purge the FIFO on 115200,8N1. Since the other
      driver fired after each byte it had ~5.47ms time to react. This
      _may_ cause problems if one relies on no missing bytes and has no
      flow control. On the other hand we get only 85 interrupts for the
      same amount of data.

It has been only tested as console UART on am335x-evm, dra7-evm and
beagle bone. I also did some longer raw-transfers to meassure the load.

The device name is ttyS based instead of ttyO. If a ttyO based node name
is required please ask udev for it. If both driver are activated (this
and omap-serial) then this serial driver will take control over the
device due to the link order

v9…v10:
	- Tony noticed that omap3 won't show anything after waking up
	  from core off. In v9 I reworked the register restore and set
	  IER to 0 by accident. This went unnoticed because start_tx
	  usually sets ier (either due to DMA bug or due to TX-complete
	  IRQ).
	- dropped EFR and SLEEP from capabilities. We do have both but
	  nobody should touch it. We already handle SLEEP ourself.
	- make the private copy of the registers (like EFR) u8 instead
	  u32
	- drop MDR1 & DL[ML] reset in restore registers. Does not look
	  required it is set to the required value later.
	- update MDR1 & SCR only if changed.
	- set MDR1 as the last thing. The errata says that we should
	  setup everything before MDR1 set.
	- avoid div by 0 in omap_8250_get_divisor() if baud rate gets
	  very large (Frans Klaver fixed the same thing omap-serial)
	- drop "is in early stage" from Kconfig.
v8…v9:
	- less on a file seems to hang the am335x after a while. I
	  believe I introduce this bug a while ago since I can reproduce
	  this prior to v8. Fixed by redoing the omap8250_restore_regs()
v7…v8:
	- redo the register write. There is now one function for that
	  which is used from set_termios() and runtime-resume.
	- drop PORT_OMAP_16750 and move the setup to the omap file. We
	  have our own set termios function anyway (Heikki Krogerus)
	- use MEM instead of MEM32. TRM of AM/DM37x says that 32bit
	  access on THR might result in data abort. We only need 32bit
	  access in the errata function which is before we use 8250's
	  read function so it doesn't matter.
v4…v7:
	- change trigger levels after some tests with raw transfers.
v3…v4:
	- drop RS485 support
	- wire up ->throttle / ->unthrottle
v2…v3:
	- wire up startup & shutdown for wakeup-irq handling.
	- RS485 handling (well the core does).

v1…v2:
	- added runtime PM. Could somebody could please double check
	  this?
	- added omap_8250_set_termios()

Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Tested-by: Frans Klaver <frans.klaver@xsens.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_omap.c | 914 ++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig     |   9 +
 drivers/tty/serial/8250/Makefile    |   1 +
 3 files changed, 924 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_omap.c

diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
new file mode 100644
index 000000000000..2f653c48639d
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -0,0 +1,914 @@
+/*
+ * 8250-core based driver for the OMAP internal UART
+ *
+ * based on omap-serial.c, Copyright (C) 2010 Texas Instruments.
+ *
+ * Copyright (C) 2014 Sebastian Andrzej Siewior
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/console.h>
+#include <linux/pm_qos.h>
+
+#include "8250.h"
+
+#define DEFAULT_CLK_SPEED	48000000
+
+#define UART_ERRATA_i202_MDR1_ACCESS	(1 << 0)
+#define OMAP_UART_WER_HAS_TX_WAKEUP	(1 << 1)
+
+#define OMAP_UART_FCR_RX_TRIG		6
+#define OMAP_UART_FCR_TX_TRIG		4
+
+/* SCR register bitmasks */
+#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK	(1 << 7)
+#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK	(1 << 6)
+#define OMAP_UART_SCR_TX_EMPTY			(1 << 3)
+#define OMAP_UART_SCR_DMAMODE_MASK		(3 << 1)
+#define OMAP_UART_SCR_DMAMODE_1			(1 << 1)
+#define OMAP_UART_SCR_DMAMODE_CTL		(1 << 0)
+
+/* MVR register bitmasks */
+#define OMAP_UART_MVR_SCHEME_SHIFT	30
+#define OMAP_UART_LEGACY_MVR_MAJ_MASK	0xf0
+#define OMAP_UART_LEGACY_MVR_MAJ_SHIFT	4
+#define OMAP_UART_LEGACY_MVR_MIN_MASK	0x0f
+#define OMAP_UART_MVR_MAJ_MASK		0x700
+#define OMAP_UART_MVR_MAJ_SHIFT		8
+#define OMAP_UART_MVR_MIN_MASK		0x3f
+
+#define UART_TI752_TLR_TX	0
+#define UART_TI752_TLR_RX	4
+
+#define TRIGGER_TLR_MASK(x)	((x & 0x3c) >> 2)
+#define TRIGGER_FCR_MASK(x)	(x & 3)
+
+/* Enable XON/XOFF flow control on output */
+#define OMAP_UART_SW_TX		0x08
+/* Enable XON/XOFF flow control on input */
+#define OMAP_UART_SW_RX		0x02
+
+#define OMAP_UART_WER_MOD_WKUP	0x7f
+#define OMAP_UART_TX_WAKEUP_EN	(1 << 7)
+
+#define TX_TRIGGER	1
+#define RX_TRIGGER	48
+
+#define OMAP_UART_TCR_RESTORE(x)	((x / 4) << 4)
+#define OMAP_UART_TCR_HALT(x)		((x / 4) << 0)
+
+#define UART_BUILD_REVISION(x, y)	(((x) << 8) | (y))
+
+#define OMAP_UART_REV_46 0x0406
+#define OMAP_UART_REV_52 0x0502
+#define OMAP_UART_REV_63 0x0603
+
+struct omap8250_priv {
+	int line;
+	u8 habit;
+	u8 mdr1;
+	u8 efr;
+	u8 scr;
+	u8 wer;
+	u8 xon;
+	u8 xoff;
+	u16 quot;
+
+	bool is_suspending;
+	int wakeirq;
+	int wakeups_enabled;
+	u32 latency;
+	u32 calc_latency;
+	struct pm_qos_request pm_qos_request;
+	struct work_struct qos_work;
+	struct uart_8250_dma omap8250_dma;
+};
+
+static u32 uart_read(struct uart_8250_port *up, u32 reg)
+{
+	return readl(up->port.membase + (reg << up->port.regshift));
+}
+
+/*
+ * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460)
+ * The access to uart register after MDR1 Access
+ * causes UART to corrupt data.
+ *
+ * Need a delay =
+ * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
+ * give 10 times as much
+ */
+static void omap_8250_mdr1_errataset(struct uart_8250_port *up,
+				     struct omap8250_priv *priv)
+{
+	u8 timeout = 255;
+	u8 old_mdr1;
+
+	old_mdr1 = serial_in(up, UART_OMAP_MDR1);
+	if (old_mdr1 == priv->mdr1)
+		return;
+
+	serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+	udelay(2);
+	serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
+			UART_FCR_CLEAR_RCVR);
+	/*
+	 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+	 * TX_FIFO_E bit is 1.
+	 */
+	while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
+				(UART_LSR_THRE | UART_LSR_DR))) {
+		timeout--;
+		if (!timeout) {
+			/* Should *never* happen. we warn and carry on */
+			dev_crit(up->port.dev, "Errata i202: timedout %x\n",
+				 serial_in(up, UART_LSR));
+			break;
+		}
+		udelay(1);
+	}
+}
+
+static void omap_8250_get_divisor(struct uart_port *port, unsigned int baud,
+				  struct omap8250_priv *priv)
+{
+	unsigned int uartclk = port->uartclk;
+	unsigned int div_13, div_16;
+	unsigned int abs_d13, abs_d16;
+
+	/*
+	 * Old custom speed handling.
+	 */
+	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
+		priv->quot = port->custom_divisor & 0xffff;
+		/*
+		 * I assume that nobody is using this. But hey, if somebody
+		 * would like to specify the divisor _and_ the mode then the
+		 * driver is ready and waiting for it.
+		 */
+		if (port->custom_divisor & (1 << 16))
+			priv->mdr1 = UART_OMAP_MDR1_13X_MODE;
+		else
+			priv->mdr1 = UART_OMAP_MDR1_16X_MODE;
+		return;
+	}
+	div_13 = DIV_ROUND_CLOSEST(uartclk, 13 * baud);
+	div_16 = DIV_ROUND_CLOSEST(uartclk, 16 * baud);
+
+	if (!div_13)
+		div_13 = 1;
+	if (!div_16)
+		div_16 = 1;
+
+	abs_d13 = abs(baud - uartclk / 13 / div_13);
+	abs_d16 = abs(baud - uartclk / 16 / div_16);
+
+	if (abs_d13 >= abs_d16) {
+		priv->mdr1 = UART_OMAP_MDR1_16X_MODE;
+		priv->quot = div_16;
+	} else {
+		priv->mdr1 = UART_OMAP_MDR1_13X_MODE;
+		priv->quot = div_13;
+	}
+}
+
+static void omap8250_update_scr(struct uart_8250_port *up,
+				struct omap8250_priv *priv)
+{
+	u8 old_scr;
+
+	old_scr = serial_in(up, UART_OMAP_SCR);
+	if (old_scr == priv->scr)
+		return;
+
+	/*
+	 * The manual recommends not to enable the DMA mode selector in the SCR
+	 * (instead of the FCR) register _and_ selecting the DMA mode as one
+	 * register write because this may lead to malfunction.
+	 */
+	if (priv->scr & OMAP_UART_SCR_DMAMODE_MASK)
+		serial_out(up, UART_OMAP_SCR,
+			   priv->scr & ~OMAP_UART_SCR_DMAMODE_MASK);
+	serial_out(up, UART_OMAP_SCR, priv->scr);
+}
+
+static void omap8250_restore_regs(struct uart_8250_port *up)
+{
+	struct omap8250_priv *priv = up->port.private_data;
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, UART_EFR_ECB);
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_MCR, UART_MCR_TCRTLR);
+	serial_out(up, UART_FCR, up->fcr);
+
+	omap8250_update_scr(up, priv);
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) |
+			OMAP_UART_TCR_HALT(52));
+	serial_out(up, UART_TI752_TLR,
+		   TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX |
+		   TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX);
+
+	serial_out(up, UART_LCR, 0);
+
+	/* drop TCR + TLR access, we setup XON/XOFF later */
+	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_IER, up->ier);
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_dl_write(up, priv->quot);
+
+	serial_out(up, UART_EFR, priv->efr);
+
+	/* Configure flow control */
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_XON1, priv->xon);
+	serial_out(up, UART_XOFF1, priv->xoff);
+
+	serial_out(up, UART_LCR, up->lcr);
+	/* need mode A for FCR */
+	if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_8250_mdr1_errataset(up, priv);
+	else
+		serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+	up->port.ops->set_mctrl(&up->port, up->port.mctrl);
+}
+
+/*
+ * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have
+ * some differences in how we want to handle flow control.
+ */
+static void omap_8250_set_termios(struct uart_port *port,
+				  struct ktermios *termios,
+				  struct ktermios *old)
+{
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+	struct omap8250_priv *priv = up->port.private_data;
+	unsigned char cval = 0;
+	unsigned int baud;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		cval = UART_LCR_WLEN5;
+		break;
+	case CS6:
+		cval = UART_LCR_WLEN6;
+		break;
+	case CS7:
+		cval = UART_LCR_WLEN7;
+		break;
+	default:
+	case CS8:
+		cval = UART_LCR_WLEN8;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval |= UART_LCR_STOP;
+	if (termios->c_cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(termios->c_cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+	if (termios->c_cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 13);
+	omap_8250_get_divisor(port, baud, priv);
+
+	/*
+	 * Ok, we're now changing the port state. Do it with
+	 * interrupts disabled.
+	 */
+	pm_runtime_get_sync(port->dev);
+	spin_lock_irq(&port->lock);
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (termios->c_iflag & INPCK)
+		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (termios->c_iflag & (IGNBRK | PARMRK))
+		up->port.read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	up->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		up->port.ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			up->port.ignore_status_mask |= UART_LSR_OE;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		up->port.ignore_status_mask |= UART_LSR_DR;
+
+	/*
+	 * Modem status interrupts
+	 */
+	up->ier &= ~UART_IER_MSI;
+	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+		up->ier |= UART_IER_MSI;
+
+	up->lcr = cval;
+	/* Up to here it was mostly serial8250_do_set_termios() */
+
+	/*
+	 * We enable TRIG_GRANU for RX and TX and additionaly we set
+	 * SCR_TX_EMPTY bit. The result is the following:
+	 * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt.
+	 * - less than RX_TRIGGER number of bytes will also cause an interrupt
+	 *   once the UART decides that there no new bytes arriving.
+	 * - Once THRE is enabled, the interrupt will be fired once the FIFO is
+	 *   empty - the trigger level is ignored here.
+	 *
+	 * Once DMA is enabled:
+	 * - UART will assert the TX DMA line once there is room for TX_TRIGGER
+	 *   bytes in the TX FIFO. On each assert the DMA engine will move
+	 *   TX_TRIGGER bytes into the FIFO.
+	 * - UART will assert the RX DMA line once there are RX_TRIGGER bytes in
+	 *   the FIFO and move RX_TRIGGER bytes.
+	 * This is because threshold and trigger values are the same.
+	 */
+	up->fcr = UART_FCR_ENABLE_FIFO;
+	up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG;
+	up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG;
+
+	priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY |
+		OMAP_UART_SCR_TX_TRIG_GRANU1_MASK;
+
+	priv->xon = termios->c_cc[VSTART];
+	priv->xoff = termios->c_cc[VSTOP];
+
+	priv->efr = 0;
+	up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY);
+	if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
+		/* Enable AUTORTS and AUTOCTS */
+		priv->efr |= UART_EFR_CTS | UART_EFR_RTS;
+
+		/* Ensure MCR RTS is asserted */
+		up->mcr |= UART_MCR_RTS;
+	} else	if (up->port.flags & UPF_SOFT_FLOW) {
+		/*
+		 * IXON Flag:
+		 * Enable XON/XOFF flow control on input.
+		 * Receiver compares XON1, XOFF1.
+		 */
+		if (termios->c_iflag & IXON)
+			priv->efr |= OMAP_UART_SW_RX;
+
+		/*
+		 * IXOFF Flag:
+		 * Enable XON/XOFF flow control on output.
+		 * Transmit XON1, XOFF1
+		 */
+		if (termios->c_iflag & IXOFF)
+			priv->efr |= OMAP_UART_SW_TX;
+
+		/*
+		 * IXANY Flag:
+		 * Enable any character to restart output.
+		 * Operation resumes after receiving any
+		 * character after recognition of the XOFF character
+		 */
+		if (termios->c_iflag & IXANY)
+			up->mcr |= UART_MCR_XONANY;
+	}
+	omap8250_restore_regs(up);
+
+	spin_unlock_irq(&up->port.lock);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+
+	/* calculate wakeup latency constraint */
+	priv->calc_latency = USEC_PER_SEC * 64 * 8 / baud;
+	priv->latency = priv->calc_latency;
+
+	schedule_work(&priv->qos_work);
+
+	/* Don't rewrite B0 */
+	if (tty_termios_baud_rate(termios))
+		tty_termios_encode_baud_rate(termios, baud, baud);
+}
+
+/* same as 8250 except that we may have extra flow bits set in EFR */
+static void omap_8250_pm(struct uart_port *port, unsigned int state,
+			 unsigned int oldstate)
+{
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+	struct omap8250_priv *priv = up->port.private_data;
+
+	pm_runtime_get_sync(port->dev);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, priv->efr | UART_EFR_ECB);
+	serial_out(up, UART_LCR, 0);
+
+	serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, priv->efr);
+	serial_out(up, UART_LCR, 0);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+}
+
+static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
+					      struct omap8250_priv *priv)
+{
+	u32 mvr, scheme;
+	u16 revision, major, minor;
+
+	mvr = uart_read(up, UART_OMAP_MVER);
+
+	/* Check revision register scheme */
+	scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT;
+
+	switch (scheme) {
+	case 0: /* Legacy Scheme: OMAP2/3 */
+		/* MINOR_REV[0:4], MAJOR_REV[4:7] */
+		major = (mvr & OMAP_UART_LEGACY_MVR_MAJ_MASK) >>
+			OMAP_UART_LEGACY_MVR_MAJ_SHIFT;
+		minor = (mvr & OMAP_UART_LEGACY_MVR_MIN_MASK);
+		break;
+	case 1:
+		/* New Scheme: OMAP4+ */
+		/* MINOR_REV[0:5], MAJOR_REV[8:10] */
+		major = (mvr & OMAP_UART_MVR_MAJ_MASK) >>
+			OMAP_UART_MVR_MAJ_SHIFT;
+		minor = (mvr & OMAP_UART_MVR_MIN_MASK);
+		break;
+	default:
+		dev_warn(up->port.dev,
+			 "Unknown revision, defaulting to highest\n");
+		/* highest possible revision */
+		major = 0xff;
+		minor = 0xff;
+	}
+	/* normalize revision for the driver */
+	revision = UART_BUILD_REVISION(major, minor);
+
+	switch (revision) {
+	case OMAP_UART_REV_46:
+		priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
+		break;
+	case OMAP_UART_REV_52:
+		priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+				OMAP_UART_WER_HAS_TX_WAKEUP;
+		break;
+	case OMAP_UART_REV_63:
+		priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+			OMAP_UART_WER_HAS_TX_WAKEUP;
+		break;
+	default:
+		break;
+	}
+}
+
+static void omap8250_uart_qos_work(struct work_struct *work)
+{
+	struct omap8250_priv *priv;
+
+	priv = container_of(work, struct omap8250_priv, qos_work);
+	pm_qos_update_request(&priv->pm_qos_request, priv->latency);
+}
+
+static irqreturn_t omap_wake_irq(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	int ret;
+
+	ret = port->handle_irq(port);
+	if (ret)
+		return IRQ_HANDLED;
+	return IRQ_NONE;
+}
+
+static int omap_8250_startup(struct uart_port *port)
+{
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+	struct omap8250_priv *priv = port->private_data;
+
+	int ret;
+
+	if (priv->wakeirq) {
+		ret = request_irq(priv->wakeirq, omap_wake_irq,
+				  port->irqflags, "uart wakeup irq", port);
+		if (ret)
+			return ret;
+		disable_irq(priv->wakeirq);
+	}
+
+	pm_runtime_get_sync(port->dev);
+
+	ret = serial8250_do_startup(port);
+	if (ret)
+		goto err;
+
+#ifdef CONFIG_PM_RUNTIME
+	up->capabilities |= UART_CAP_RPM;
+#endif
+
+	/* Enable module level wake up */
+	priv->wer = OMAP_UART_WER_MOD_WKUP;
+	if (priv->habit & OMAP_UART_WER_HAS_TX_WAKEUP)
+		priv->wer |= OMAP_UART_TX_WAKEUP_EN;
+	serial_out(up, UART_OMAP_WER, priv->wer);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+	return 0;
+err:
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+	if (priv->wakeirq)
+		free_irq(priv->wakeirq, port);
+	return ret;
+}
+
+static void omap_8250_shutdown(struct uart_port *port)
+{
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+	struct omap8250_priv *priv = port->private_data;
+
+	flush_work(&priv->qos_work);
+
+	pm_runtime_get_sync(port->dev);
+
+	serial_out(up, UART_OMAP_WER, 0);
+	serial8250_do_shutdown(port);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+
+	if (priv->wakeirq)
+		free_irq(priv->wakeirq, port);
+}
+
+static void omap_8250_throttle(struct uart_port *port)
+{
+	unsigned long flags;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+
+	pm_runtime_get_sync(port->dev);
+
+	spin_lock_irqsave(&port->lock, flags);
+	up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+	serial_out(up, UART_IER, up->ier);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+}
+
+static void omap_8250_unthrottle(struct uart_port *port)
+{
+	unsigned long flags;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+
+	pm_runtime_get_sync(port->dev);
+
+	spin_lock_irqsave(&port->lock, flags);
+	up->ier |= UART_IER_RLSI | UART_IER_RDI;
+	serial_out(up, UART_IER, up->ier);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+}
+
+static int omap8250_probe(struct platform_device *pdev)
+{
+	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	struct omap8250_priv *priv;
+	struct uart_8250_port up;
+	int ret;
+	void __iomem *membase;
+
+	if (!regs || !irq) {
+		dev_err(&pdev->dev, "missing registers or irq\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	membase = devm_ioremap_nocache(&pdev->dev, regs->start,
+				       resource_size(regs));
+	if (!membase)
+		return -ENODEV;
+
+	memset(&up, 0, sizeof(up));
+	up.port.dev = &pdev->dev;
+	up.port.mapbase = regs->start;
+	up.port.membase = membase;
+	up.port.irq = irq->start;
+	/*
+	 * It claims to be 16C750 compatible however it is a little different.
+	 * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to
+	 * have) is enabled via EFR instead of MCR. The type is set here 8250
+	 * just to get things going. UNKNOWN does not work for a few reasons and
+	 * we don't need our own type since we don't use 8250's set_termios()
+	 * or pm callback.
+	 */
+	up.port.type = PORT_8250;
+	up.port.iotype = UPIO_MEM;
+	up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW |
+		UPF_HARD_FLOW;
+	up.port.private_data = priv;
+
+	up.port.regshift = 2;
+	up.port.fifosize = 64;
+	up.tx_loadsz = 64;
+	up.capabilities = UART_CAP_FIFO;
+#ifdef CONFIG_PM_RUNTIME
+	/*
+	 * PM_RUNTIME is mostly transparent. However to do it right we need to a
+	 * TX empty interrupt before we can put the device to auto idle. So if
+	 * PM_RUNTIME is not enabled we don't add that flag and can spare that
+	 * one extra interrupt in the TX path.
+	 */
+	up.capabilities |= UART_CAP_RPM;
+#endif
+	up.port.set_termios = omap_8250_set_termios;
+	up.port.pm = omap_8250_pm;
+	up.port.startup = omap_8250_startup;
+	up.port.shutdown = omap_8250_shutdown;
+	up.port.throttle = omap_8250_throttle;
+	up.port.unthrottle = omap_8250_unthrottle;
+
+	if (pdev->dev.of_node) {
+		up.port.line = of_alias_get_id(pdev->dev.of_node, "serial");
+		of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+				     &up.port.uartclk);
+		priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+	} else {
+		up.port.line = pdev->id;
+	}
+
+	if (up.port.line < 0) {
+		dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n",
+			up.port.line);
+		return -ENODEV;
+	}
+	if (!up.port.uartclk) {
+		up.port.uartclk = DEFAULT_CLK_SPEED;
+		dev_warn(&pdev->dev,
+			 "No clock speed specified: using default: %d\n",
+			 DEFAULT_CLK_SPEED);
+	}
+
+	priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+	priv->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+	pm_qos_add_request(&priv->pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
+			   priv->latency);
+	INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);
+
+	device_init_wakeup(&pdev->dev, true);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
+
+	pm_runtime_irq_safe(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	pm_runtime_get_sync(&pdev->dev);
+
+	omap_serial_fill_features_erratas(&up, priv);
+	ret = serial8250_register_8250_port(&up);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to register 8250 port\n");
+		goto err;
+	}
+	priv->line = ret;
+	platform_set_drvdata(pdev, priv);
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_put_autosuspend(&pdev->dev);
+	return 0;
+err:
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	return ret;
+}
+
+static int omap8250_remove(struct platform_device *pdev)
+{
+	struct omap8250_priv *priv = platform_get_drvdata(pdev);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	serial8250_unregister_port(priv->line);
+	pm_qos_remove_request(&priv->pm_qos_request);
+	device_init_wakeup(&pdev->dev, false);
+	return 0;
+}
+
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
+
+static inline void omap8250_enable_wakeirq(struct omap8250_priv *priv,
+					   bool enable)
+{
+	if (!priv->wakeirq)
+		return;
+
+	if (enable)
+		enable_irq(priv->wakeirq);
+	else
+		disable_irq_nosync(priv->wakeirq);
+}
+
+static void omap8250_enable_wakeup(struct omap8250_priv *priv,
+				   bool enable)
+{
+	if (enable == priv->wakeups_enabled)
+		return;
+
+	omap8250_enable_wakeirq(priv, enable);
+	priv->wakeups_enabled = enable;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int omap8250_prepare(struct device *dev)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(dev);
+
+	if (!priv)
+		return 0;
+	priv->is_suspending = true;
+	return 0;
+}
+
+static void omap8250_complete(struct device *dev)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(dev);
+
+	if (!priv)
+		return;
+	priv->is_suspending = false;
+}
+
+static int omap8250_suspend(struct device *dev)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(priv->line);
+	flush_work(&priv->qos_work);
+
+	if (device_may_wakeup(dev))
+		omap8250_enable_wakeup(priv, true);
+	else
+		omap8250_enable_wakeup(priv, false);
+	return 0;
+}
+
+static int omap8250_resume(struct device *dev)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		omap8250_enable_wakeup(priv, false);
+
+	serial8250_resume_port(priv->line);
+	return 0;
+}
+#else
+#define omap8250_prepare NULL
+#define omap8250_complete NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int omap8250_lost_context(struct uart_8250_port *up)
+{
+	u32 val;
+
+	val = serial_in(up, UART_OMAP_MDR1);
+	/*
+	 * If we lose context, then MDR1 is set to its reset value which is
+	 * UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
+	 * or 16x but never to disable again.
+	 */
+	if (val == UART_OMAP_MDR1_DISABLE)
+		return 1;
+	return 0;
+}
+
+static int omap8250_runtime_suspend(struct device *dev)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(dev);
+	struct uart_8250_port *up;
+
+	up = serial8250_get_port(priv->line);
+	/*
+	 * When using 'no_console_suspend', the console UART must not be
+	 * suspended. Since driver suspend is managed by runtime suspend,
+	 * preventing runtime suspend (by returning error) will keep device
+	 * active during suspend.
+	 */
+	if (priv->is_suspending && !console_suspend_enabled) {
+		if (uart_console(&up->port))
+			return -EBUSY;
+	}
+
+	omap8250_enable_wakeup(priv, true);
+
+	priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+	schedule_work(&priv->qos_work);
+
+	return 0;
+}
+
+static int omap8250_runtime_resume(struct device *dev)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(dev);
+	struct uart_8250_port *up;
+	int loss_cntx;
+
+	/* In case runtime-pm tries this before we are setup */
+	if (!priv)
+		return 0;
+
+	up = serial8250_get_port(priv->line);
+	omap8250_enable_wakeup(priv, false);
+	loss_cntx = omap8250_lost_context(up);
+
+	if (loss_cntx)
+		omap8250_restore_regs(up);
+
+	priv->latency = priv->calc_latency;
+	schedule_work(&priv->qos_work);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap8250_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume)
+	SET_RUNTIME_PM_OPS(omap8250_runtime_suspend,
+			   omap8250_runtime_resume, NULL)
+	.prepare        = omap8250_prepare,
+	.complete       = omap8250_complete,
+};
+
+static const struct of_device_id omap8250_dt_ids[] = {
+	{ .compatible = "ti,omap2-uart" },
+	{ .compatible = "ti,omap3-uart" },
+	{ .compatible = "ti,omap4-uart" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
+
+static struct platform_driver omap8250_platform_driver = {
+	.driver = {
+		.name		= "omap8250",
+		.pm		= &omap8250_dev_pm_ops,
+		.of_match_table = omap8250_dt_ids,
+		.owner		= THIS_MODULE,
+	},
+	.probe			= omap8250_probe,
+	.remove			= omap8250_remove,
+};
+module_platform_driver(omap8250_platform_driver);
+
+MODULE_AUTHOR("Sebastian Andrzej Siewior");
+MODULE_DESCRIPTION("OMAP 8250 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 21eca79224e4..5d3d65c0733e 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -299,6 +299,15 @@ config SERIAL_8250_RT288X
 	  serial port, say Y to this option. The driver can handle up to 2 serial
 	  ports. If unsure, say N.
 
+config SERIAL_8250_OMAP
+	tristate "Support for OMAP internal UART (8250 based driver)"
+	depends on SERIAL_8250 && ARCH_OMAP2PLUS
+	help
+	  If you have a machine based on an Texas Instruments OMAP CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  This driver uses ttyS instead of ttyO.
+
 config SERIAL_8250_FINTEK
 	tristate "Support for Fintek F81216A LPC to 4 UART"
 	depends on SERIAL_8250 && PNP
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 5256b894e46a..31e7cdc6865c 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
+obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
 obj-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
 obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 04/13] tty: serial: 8250_dma: handle error on TX submit
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (2 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 03/13] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 05/13] tty: serial: 8250_dma: keep own book keeping about RX transfers Sebastian Andrzej Siewior
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

Right now it is possible that serial8250_tx_dma() fails and returns
-EBUSY. The caller (serial8250_start_tx()) will then enable
UART_IER_THRI which will generate an interrupt once the TX FIFO is
empty.
In serial8250_handle_irq() nothing will happen because up->dma is set
and so serial8250_tx_chars() won't be invoked. We end up with plenty of
interrupts and some "too much work for irq" output.

This patch introduces dma_tx_err in struct uart_8250_port to signal that
the last invocation of serial8250_tx_dma() failed so we can fill the TX
FIFO manually. Should the next invocation of serial8250_start_tx()
succeed then the dma_tx_err flag along with the THRI bit is removed and
DMA only usage may continue.

Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250.h      |  1 +
 drivers/tty/serial/8250/8250_core.c |  3 ++-
 drivers/tty/serial/8250/8250_dma.c  | 30 +++++++++++++++++++++++++-----
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 1bcb4b2141a6..a63d198f8d03 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -41,6 +41,7 @@ struct uart_8250_dma {
 	size_t			tx_size;
 
 	unsigned char		tx_running:1;
+	unsigned char		tx_err: 1;
 };
 
 struct old_serial_port {
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 159b72471622..ea57c87f8528 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1594,7 +1594,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 			status = serial8250_rx_chars(up, status);
 	}
 	serial8250_modem_status(up);
-	if (!up->dma && (status & UART_LSR_THRE))
+	if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+	    (status & UART_LSR_THRE))
 		serial8250_tx_chars(up);
 
 	spin_unlock_irqrestore(&port->lock, flags);
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 148ffe4c232f..69e54abb6e71 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -36,8 +36,16 @@ static void __dma_tx_complete(void *param)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&p->port);
 
-	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
-		serial8250_tx_dma(p);
+	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
+		int ret;
+
+		ret = serial8250_tx_dma(p);
+		if (ret) {
+			dma->tx_err = 1;
+			p->ier |= UART_IER_THRI;
+			serial_port_out(&p->port, UART_IER, p->ier);
+		}
+	}
 
 	spin_unlock_irqrestore(&p->port.lock, flags);
 }
@@ -69,6 +77,7 @@ int serial8250_tx_dma(struct uart_8250_port *p)
 	struct uart_8250_dma		*dma = p->dma;
 	struct circ_buf			*xmit = &p->port.state->xmit;
 	struct dma_async_tx_descriptor	*desc;
+	int ret;
 
 	if (uart_tx_stopped(&p->port) || dma->tx_running ||
 	    uart_circ_empty(xmit))
@@ -80,8 +89,10 @@ int serial8250_tx_dma(struct uart_8250_port *p)
 					   dma->tx_addr + xmit->tail,
 					   dma->tx_size, DMA_MEM_TO_DEV,
 					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	if (!desc)
-		return -EBUSY;
+	if (!desc) {
+		ret = -EBUSY;
+		goto err;
+	}
 
 	dma->tx_running = 1;
 
@@ -94,8 +105,17 @@ int serial8250_tx_dma(struct uart_8250_port *p)
 				   UART_XMIT_SIZE, DMA_TO_DEVICE);
 
 	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;
+			serial_out(p, UART_IER, p->ier);
+		}
+	}
 	return 0;
+err:
+	dma->tx_err = 1;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(serial8250_tx_dma);
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 05/13] tty: serial: 8250_dma: keep own book keeping about RX transfers
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (3 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 04/13] tty: serial: 8250_dma: handle error on TX submit Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 06/13] tty: serial: 8250: allow to use custom DMA implementation Sebastian Andrzej Siewior
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior, vinod.koul

After dmaengine_terminate_all() has been invoked then both DMA drivers
(edma and omap-dma) do not invoke dma_cookie_complete() to mark the
transfer as complete. This dma_cookie_complete() is performed by the
Synopsys DesignWare driver which is probably the only one that is used
by omap8250-dma and hence don't see following problem…
…which is that once a RX transfer has been terminated then following
query of channel status reports DMA_IN_PROGRESS (again: the actual
transfer has been canceled, there is nothing going on anymore).

This means that serial8250_rx_dma() never enqueues another DMA transfer
because it (wrongly) assumes that there is a transer already pending.

Vinod Koul refuses to accept a patch which adds this
dma_cookie_complete() to both drivers and so dmaengine_tx_status() would
report DMA_COMPLETE instead (and behave like the Synopsys DesignWare
driver already does). He argues that I am not allowed to use the cookie
to query the status and that the driver already cleaned everything up after
the invokation of dmaengine_terminate_all().

To end this I add a bookkeeping whether or not a RX-transfer has been
started to the 8250-dma code. It has already been done for the TX side.
*Now* we learn about the RX status based on our bookkeeping and don't
need dmaengine_tx_status() for this anymore.

Cc: vinod.koul@intel.com
Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250.h     |  1 +
 drivers/tty/serial/8250/8250_dma.c | 10 ++++------
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index a63d198f8d03..ebab625179d4 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -42,6 +42,7 @@ struct uart_8250_dma {
 
 	unsigned char		tx_running:1;
 	unsigned char		tx_err: 1;
+	unsigned char		rx_running:1;
 };
 
 struct old_serial_port {
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 69e54abb6e71..db9eda3c12d6 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -61,6 +61,7 @@ static void __dma_rx_complete(void *param)
 	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
 				dma->rx_size, DMA_FROM_DEVICE);
 
+	dma->rx_running = 0;
 	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
 	dmaengine_terminate_all(dma->rxchan);
 
@@ -123,10 +124,6 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 {
 	struct uart_8250_dma		*dma = p->dma;
 	struct dma_async_tx_descriptor	*desc;
-	struct dma_tx_state		state;
-	int				dma_status;
-
-	dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
 
 	switch (iir & 0x3f) {
 	case UART_IIR_RLSI:
@@ -137,7 +134,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 		 * If RCVR FIFO trigger level was not reached, complete the
 		 * transfer and let 8250_core copy the remaining data.
 		 */
-		if (dma_status == DMA_IN_PROGRESS) {
+		if (dma->rx_running) {
 			dmaengine_pause(dma->rxchan);
 			__dma_rx_complete(p);
 		}
@@ -146,7 +143,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 		break;
 	}
 
-	if (dma_status)
+	if (dma->rx_running)
 		return 0;
 
 	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
@@ -155,6 +152,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 	if (!desc)
 		return -EBUSY;
 
+	dma->rx_running = 1;
 	desc->callback = __dma_rx_complete;
 	desc->callback_param = p;
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 06/13] tty: serial: 8250: allow to use custom DMA implementation
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (4 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 05/13] tty: serial: 8250_dma: keep own book keeping about RX transfers Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 07/13] tty: serial: 8250_omap: add custom DMA-TX callback Sebastian Andrzej Siewior
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

The OMAP has a few corner cases where it needs a share of kindness of
affection to do the right thing. Heikki Krogerus suggested that instead
adding the quirks into the default DMA implementation, OMAP could get
its own copy of the function. And Alan suggested the same thing so here
we go.

This patch provides callbacks for custom TX/RX DMA implementation. If
there are not setup / used, then the default (current) implementation is
used.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250.h      |  3 +++
 drivers/tty/serial/8250/8250_core.c | 11 ++++++++---
 drivers/tty/serial/8250/8250_dma.c  |  2 --
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index ebab625179d4..4bb831ab5db0 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -16,6 +16,9 @@
 #include <linux/dmaengine.h>
 
 struct uart_8250_dma {
+	int (*tx_dma)(struct uart_8250_port *p);
+	int (*rx_dma)(struct uart_8250_port *p, unsigned int iir);
+
 	dma_filter_fn		fn;
 	void			*rx_param;
 	void			*tx_param;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index ea57c87f8528..93b0799936fd 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1350,7 +1350,7 @@ static void serial8250_start_tx(struct uart_port *port)
 	struct uart_8250_port *up = up_to_u8250p(port);
 
 	serial8250_rpm_get_tx(up);
-	if (up->dma && !serial8250_tx_dma(up)) {
+	if (up->dma && !up->dma->tx_dma(up)) {
 		return;
 	} else if (!(up->ier & UART_IER_THRI)) {
 		up->ier |= UART_IER_THRI;
@@ -1588,7 +1588,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 
 	if (status & (UART_LSR_DR | UART_LSR_BI)) {
 		if (up->dma)
-			dma_err = serial8250_rx_dma(up, iir);
+			dma_err = up->dma->rx_dma(up, iir);
 
 		if (!up->dma || dma_err)
 			status = serial8250_rx_chars(up, status);
@@ -3624,8 +3624,13 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 			uart->dl_read = up->dl_read;
 		if (up->dl_write)
 			uart->dl_write = up->dl_write;
-		if (up->dma)
+		if (up->dma) {
 			uart->dma = up->dma;
+			if (!uart->dma->tx_dma)
+				uart->dma->tx_dma = serial8250_tx_dma;
+			if (!uart->dma->rx_dma)
+				uart->dma->rx_dma = serial8250_rx_dma;
+		}
 
 		if (serial8250_isa_config != NULL)
 			serial8250_isa_config(0, &uart->port,
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index db9eda3c12d6..258430b72039 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -118,7 +118,6 @@ int serial8250_tx_dma(struct uart_8250_port *p)
 	dma->tx_err = 1;
 	return ret;
 }
-EXPORT_SYMBOL_GPL(serial8250_tx_dma);
 
 int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 {
@@ -165,7 +164,6 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(serial8250_rx_dma);
 
 int serial8250_request_dma(struct uart_8250_port *p)
 {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 07/13] tty: serial: 8250_omap: add custom DMA-TX callback
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (5 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 06/13] tty: serial: 8250: allow to use custom DMA implementation Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 08/13] tty: serial: 8250_omap: add custom DMA-RX callback Sebastian Andrzej Siewior
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

This patch provides mostly a copy of serial8250_tx_dma() +
__dma_tx_complete() with the following extensions:

- DMA bug
  At least on AM335x the following problem exists: Even if the TX FIFO is
  empty and a TX transfer is programmed (and started) the UART does not
  trigger the DMA transfer.
  After $TRESHOLD number of bytes have been written to the FIFO manually the
  UART reevaluates the whole situation and decides that now there is enough
  room in the FIFO and so the transfer begins.
  This problem has not been seen on DRA7 or beagle board xm (OMAP3). I am not
  sure if this is UART-IP core specific or DMA engine.

  The workaround is to use a threshold of one byte, program the DMA
  transfer minus one byte and then to put the first byte into the FIFO to
  kick start the transfer.

- support for runtime PM
  RPM is enabled on start_tx(). We can't disable RPM on DMA complete callback
  because there is still data in the FIFO which is being sent. We have to wait
  until the FIFO is empty before we disable it.
  For this to happen we fake a TX sent error and enable THRI. Once the
  FIFO is empty we receive an interrupt and since the TTY-buffer is still
  empty we "put RPM" via __stop_tx(). Should it been filed then in the
  start_tx() path we should program the DMA transfer and remove the error
  flag and the THRI bit.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_omap.c | 144 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/serial_reg.h     |   1 +
 2 files changed, 145 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 2f653c48639d..5f183d197dfa 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -22,6 +22,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/console.h>
 #include <linux/pm_qos.h>
+#include <linux/dma-mapping.h>
 
 #include "8250.h"
 
@@ -29,6 +30,7 @@
 
 #define UART_ERRATA_i202_MDR1_ACCESS	(1 << 0)
 #define OMAP_UART_WER_HAS_TX_WAKEUP	(1 << 1)
+#define OMAP_DMA_TX_KICK		(1 << 2)
 
 #define OMAP_UART_FCR_RX_TRIG		6
 #define OMAP_UART_FCR_TX_TRIG		4
@@ -616,6 +618,148 @@ static void omap_8250_unthrottle(struct uart_port *port)
 	pm_runtime_put_autosuspend(port->dev);
 }
 
+#ifdef CONFIG_SERIAL_8250_DMA
+static int omap_8250_tx_dma(struct uart_8250_port *p);
+
+static void omap_8250_dma_tx_complete(void *param)
+{
+	struct uart_8250_port	*p = param;
+	struct uart_8250_dma	*dma = p->dma;
+	struct circ_buf		*xmit = &p->port.state->xmit;
+	unsigned long		flags;
+	bool			en_thri = false;
+
+	dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
+				UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+	spin_lock_irqsave(&p->port.lock, flags);
+
+	dma->tx_running = 0;
+
+	xmit->tail += dma->tx_size;
+	xmit->tail &= UART_XMIT_SIZE - 1;
+	p->port.icount.tx += dma->tx_size;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&p->port);
+
+	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
+		int ret;
+
+		ret = omap_8250_tx_dma(p);
+		if (ret)
+			en_thri = true;
+
+	} else if (p->capabilities & UART_CAP_RPM) {
+		en_thri = true;
+	}
+
+	if (en_thri) {
+		dma->tx_err = 1;
+		p->ier |= UART_IER_THRI;
+		serial_port_out(&p->port, UART_IER, p->ier);
+	}
+
+	spin_unlock_irqrestore(&p->port.lock, flags);
+}
+
+static int omap_8250_tx_dma(struct uart_8250_port *p)
+{
+	struct uart_8250_dma		*dma = p->dma;
+	struct omap8250_priv		*priv = p->port.private_data;
+	struct circ_buf			*xmit = &p->port.state->xmit;
+	struct dma_async_tx_descriptor	*desc;
+	unsigned int	skip_byte = 0;
+	int ret;
+
+	if (dma->tx_running)
+		return 0;
+	if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
+
+		/*
+		 * Even if no data, we need to return an error for the two cases
+		 * below so serial8250_tx_chars() is invoked and properly clears
+		 * THRI and/or runtime suspend.
+		 */
+		if (dma->tx_err || p->capabilities & UART_CAP_RPM) {
+			ret = -EBUSY;
+			goto err;
+		}
+		if (p->ier & UART_IER_THRI) {
+			p->ier &= ~UART_IER_THRI;
+			serial_out(p, UART_IER, p->ier);
+		}
+		return 0;
+	}
+
+	dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+	if (priv->habit & OMAP_DMA_TX_KICK) {
+		u8 tx_lvl;
+
+		/*
+		 * We need to put the first byte into the FIFO in order to start
+		 * the DMA transfer. For transfers smaller than four bytes we
+		 * don't bother doing DMA at all. It seem not matter if there
+		 * are still bytes in the FIFO from the last transfer (in case
+		 * we got here directly from omap_8250_dma_tx_complete()). Bytes
+		 * leaving the FIFO seem not to trigger the DMA transfer. It is
+		 * really the byte that we put into the FIFO.
+		 * If the FIFO is already full then we most likely got here from
+		 * omap_8250_dma_tx_complete(). And this means the DMA engine
+		 * just completed its work. We don't have to wait the complete
+		 * 86us at 115200,8n1 but around 60us (not to mention lower
+		 * baudrates). So in that case we take the interrupt and try
+		 * again with an empty FIFO.
+		 */
+		tx_lvl = serial_in(p, UART_OMAP_TX_LVL);
+		if (tx_lvl == p->tx_loadsz) {
+			ret = -EBUSY;
+			goto err;
+		}
+		if (dma->tx_size < 4) {
+			ret = -EINVAL;
+			goto err;
+		}
+		skip_byte = 1;
+	}
+
+	desc = dmaengine_prep_slave_single(dma->txchan,
+			dma->tx_addr + xmit->tail + skip_byte,
+			dma->tx_size - skip_byte, DMA_MEM_TO_DEV,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	dma->tx_running = 1;
+
+	desc->callback = omap_8250_dma_tx_complete;
+	desc->callback_param = p;
+
+	dma->tx_cookie = dmaengine_submit(desc);
+
+	dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
+				   UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+	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;
+		serial_out(p, UART_IER, p->ier);
+	}
+	if (skip_byte)
+		serial_out(p, UART_TX, xmit->buf[xmit->tail]);
+	return 0;
+err:
+	dma->tx_err = 1;
+	return ret;
+}
+
+#endif
+
 static int omap8250_probe(struct platform_device *pdev)
 {
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index df6c9ab6b0cd..53af3b790129 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -359,6 +359,7 @@
 #define UART_OMAP_SYSC		0x15	/* System configuration register */
 #define UART_OMAP_SYSS		0x16	/* System status register */
 #define UART_OMAP_WER		0x17	/* Wake-up enable register */
+#define UART_OMAP_TX_LVL	0x1a	/* TX FIFO level register */
 
 /*
  * These are the definitions for the MDR1 register
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 08/13] tty: serial: 8250_omap: add custom DMA-RX callback
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (6 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 07/13] tty: serial: 8250_omap: add custom DMA-TX callback Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause() Sebastian Andrzej Siewior
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

The omap needs a DMA request pending right away. If it is
enqueued once the bytes are in the FIFO then nothing will happen
and the FIFO will be later purged via RX-timeout interrupt.
This patch enqueues RX-DMA request on completion but not if it
was aborted on error. The first enqueue will happen in the driver
in startup.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_omap.c | 96 +++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 5f183d197dfa..1659858e595a 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -619,6 +619,102 @@ static void omap_8250_unthrottle(struct uart_port *port)
 }
 
 #ifdef CONFIG_SERIAL_8250_DMA
+static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir);
+
+static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
+{
+	struct uart_8250_dma    *dma = p->dma;
+	struct tty_port         *tty_port = &p->port.state->port;
+	struct dma_tx_state     state;
+	int                     count;
+
+	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
+				dma->rx_size, DMA_FROM_DEVICE);
+
+	dma->rx_running = 0;
+	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+	dmaengine_terminate_all(dma->rxchan);
+
+	count = dma->rx_size - state.residue;
+
+	tty_insert_flip_string(tty_port, dma->rx_buf, count);
+	p->port.icount.rx += count;
+	if (!error)
+		omap_8250_rx_dma(p, 0);
+
+	tty_flip_buffer_push(tty_port);
+}
+
+static void __dma_rx_complete(void *param)
+{
+	__dma_rx_do_complete(param, false);
+}
+
+static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
+{
+	struct uart_8250_dma            *dma = p->dma;
+	struct dma_async_tx_descriptor  *desc;
+
+	switch (iir & 0x3f) {
+	case UART_IIR_RLSI:
+		/* 8250_core handles errors and break interrupts */
+		if (dma->rx_running) {
+			dmaengine_pause(dma->rxchan);
+			__dma_rx_do_complete(p, true);
+		}
+		return -EIO;
+	case UART_IIR_RX_TIMEOUT:
+		/*
+		 * If RCVR FIFO trigger level was not reached, complete the
+		 * transfer and let 8250_core copy the remaining data.
+		 */
+		if (dma->rx_running) {
+			dmaengine_pause(dma->rxchan);
+			__dma_rx_do_complete(p, true);
+		}
+		return -ETIMEDOUT;
+	case UART_IIR_RDI:
+		/*
+		 * The OMAP UART is a special BEAST. If we receive RDI we _have_
+		 * a DMA transfer programmed but it didn't work. One reason is
+		 * that we were too slow and there were too many bytes in the
+		 * FIFO, the UART counted wrong and never kicked the DMA engine
+		 * to do anything. That means once we receive RDI on OMAP then
+		 * the DMA won't do anything soon so we have to cancel the DMA
+		 * transfer and purge the FIFO manually.
+		 */
+		if (dma->rx_running) {
+			dmaengine_pause(dma->rxchan);
+			__dma_rx_do_complete(p, true);
+		}
+		return -ETIMEDOUT;
+
+	default:
+		break;
+	}
+
+	if (dma->rx_running)
+		return 0;
+
+	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
+					   dma->rx_size, DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc)
+		return -EBUSY;
+
+	dma->rx_running = 1;
+	desc->callback = __dma_rx_complete;
+	desc->callback_param = p;
+
+	dma->rx_cookie = dmaengine_submit(desc);
+
+	dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
+				   dma->rx_size, DMA_FROM_DEVICE);
+
+	dma_async_issue_pending(dma->rxchan);
+	return 0;
+}
+
 static int omap_8250_tx_dma(struct uart_8250_port *p);
 
 static void omap_8250_dma_tx_complete(void *param)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause()
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (7 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 08/13] tty: serial: 8250_omap: add custom DMA-RX callback Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-10-01 12:00   ` Peter Ujfalusi
                     ` (2 more replies)
  2014-09-29 18:06 ` [PATCH 10/13] arm: dts: am33xx: add DMA properties for UART Sebastian Andrzej Siewior
                   ` (6 subsequent siblings)
  15 siblings, 3 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior, vinod.koul

I added book keeping of whether or not the 8250-dma driver has an RX
transfer pending or not so we don't BUG here if it calls
dmaengine_pause() on a channel which has not a pending transfer. Guess
what, this is not enough.
The following can be triggered with a busy RX channel and hackbench in
background:
- DMA transfer completes. The callback is delayed via
  vchan_cookie_complete() into a tasklet so it das not happen asap.
- hackbench keeps the system busy so the tasklet does not run "soon".
- the UART collected enough data and generates an "timeout"-interrupt.
  Since 8250-dma *thinks* the DMA-transfer is still pending it tries to
  cancel it via invoking dmaengine_pause() first. This causes the segfault
  because echan->edesc is NULL now that the transfer completed (however
  the callback did not run yet).

With this patch we don't BUG in the scenario described.

Cc: vinod.koul@intel.com
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/dma/edma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 7b65633f495e..123f578d6dd3 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -288,7 +288,7 @@ static int edma_slave_config(struct edma_chan *echan,
 static int edma_dma_pause(struct edma_chan *echan)
 {
 	/* Pause/Resume only allowed with cyclic mode */
-	if (!echan->edesc->cyclic)
+	if (!echan->edesc || !echan->edesc->cyclic)
 		return -EINVAL;
 
 	edma_pause(echan->ch_num);
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 10/13] arm: dts: am33xx: add DMA properties for UART
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (8 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause() Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-09-29 18:06 ` [PATCH 11/13] arm: dts: dra7: " Sebastian Andrzej Siewior
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior, devicetree

Cc: devicetree@vger.kernel.org
Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 3a0a161342ba..078a760a4a21 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -200,6 +200,8 @@
 			reg = <0x44e09000 0x2000>;
 			interrupts = <72>;
 			status = "disabled";
+			dmas = <&edma 26>, <&edma 27>;
+			dma-names = "tx", "rx";
 		};
 
 		uart1: serial@48022000 {
@@ -209,6 +211,8 @@
 			reg = <0x48022000 0x2000>;
 			interrupts = <73>;
 			status = "disabled";
+			dmas = <&edma 28>, <&edma 29>;
+			dma-names = "tx", "rx";
 		};
 
 		uart2: serial@48024000 {
@@ -218,6 +222,8 @@
 			reg = <0x48024000 0x2000>;
 			interrupts = <74>;
 			status = "disabled";
+			dmas = <&edma 30>, <&edma 31>;
+			dma-names = "tx", "rx";
 		};
 
 		uart3: serial@481a6000 {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (9 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 10/13] arm: dts: am33xx: add DMA properties for UART Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-11-04 17:02   ` Lennart Sorensen
  2014-09-29 18:06 ` [PATCH 12/13] tty: serial: 8250: omap: add custom irq handling Sebastian Andrzej Siewior
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior, devicetree

Cc: devicetree@vger.kernel.org
Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 arch/arm/boot/dts/dra7.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index d678152db4cb..f273e3811f75 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -332,6 +332,8 @@
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 			status = "disabled";
+			dmas = <&sdma 49>, <&sdma 50>;
+			dma-names = "tx", "rx";
 		};
 
 		uart2: serial@4806c000 {
@@ -341,6 +343,8 @@
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 			status = "disabled";
+			dmas = <&sdma 51>, <&sdma 52>;
+			dma-names = "tx", "rx";
 		};
 
 		uart3: serial@48020000 {
@@ -350,6 +354,8 @@
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 			status = "disabled";
+			dmas = <&sdma 53>, <&sdma 54>;
+			dma-names = "tx", "rx";
 		};
 
 		uart4: serial@4806e000 {
@@ -359,6 +365,8 @@
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
                         status = "disabled";
+			dmas = <&sdma 55>, <&sdma 56>;
+			dma-names = "tx", "rx";
 		};
 
 		uart5: serial@48066000 {
@@ -368,6 +376,8 @@
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
 			status = "disabled";
+			dmas = <&sdma 63>, <&sdma 64>;
+			dma-names = "tx", "rx";
 		};
 
 		uart6: serial@48068000 {
@@ -377,6 +387,8 @@
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 			status = "disabled";
+			dmas = <&sdma 79>, <&sdma 80>;
+			dma-names = "tx", "rx";
 		};
 
 		uart7: serial@48420000 {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 12/13] tty: serial: 8250: omap: add custom irq handling
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (10 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 11/13] arm: dts: dra7: " Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-10-09 13:19   ` Heikki Krogerus
  2014-09-29 18:06 ` [PATCH 13/13] tty: serial: 8250: omap: add dma support Sebastian Andrzej Siewior
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior, Heikki Krogerus, Peter Hurley

We have (or will have) custom DMA callbacks in the omap driver due to
the different behaviour in the RX and TX case. To make this work
we need a few changes in the IRQ handler to invoke the rx_handler again
after the "manual" mode or retry the tx_handler again before falling
back to the manual mode.

Heikki didn't want to see the extra hacks in the generic / default irq
handler and Peter wasn't too happy about an OMAP-only IRQ handler. The
way I planned it is to use this extra IRQ routine only in DMA case. If
Peter dislike this approach then I hope Heikki doesn't block changes in
the default IRQ handler :)

Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250.h      |  2 ++
 drivers/tty/serial/8250/8250_core.c |  6 ++--
 drivers/tty/serial/8250/8250_omap.c | 55 +++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 4bb831ab5db0..28097a912c10 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -119,6 +119,8 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
 }
 
 struct uart_8250_port *serial8250_get_port(int line);
+void serial8250_rpm_get(struct uart_8250_port *p);
+void serial8250_rpm_put(struct uart_8250_port *p);
 
 #if defined(__alpha__) && !defined(CONFIG_PCI)
 /*
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 93b0799936fd..6a3b4399bf3c 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -541,20 +541,22 @@ void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
 }
 EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
 
-static void serial8250_rpm_get(struct uart_8250_port *p)
+void serial8250_rpm_get(struct uart_8250_port *p)
 {
 	if (!(p->capabilities & UART_CAP_RPM))
 		return;
 	pm_runtime_get_sync(p->port.dev);
 }
+EXPORT_SYMBOL_GPL(serial8250_rpm_get);
 
-static void serial8250_rpm_put(struct uart_8250_port *p)
+void serial8250_rpm_put(struct uart_8250_port *p)
 {
 	if (!(p->capabilities & UART_CAP_RPM))
 		return;
 	pm_runtime_mark_last_busy(p->port.dev);
 	pm_runtime_put_autosuspend(p->port.dev);
 }
+EXPORT_SYMBOL_GPL(serial8250_rpm_put);
 
 /*
  * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 1659858e595a..6500547f8fda 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -13,6 +13,7 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
+#include <linux/tty_flip.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -854,6 +855,60 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
 	return ret;
 }
 
+/*
+ * This is mostly serial8250_handle_irq(). We have a slightly different DMA
+ * hoook for RX/TX and need different logic for them in the ISR. Therefore we
+ * use the default routine in the non-DMA case and this one for with DMA.
+ */
+static int omap_8250_dma_handle_irq(struct uart_port *port)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+	unsigned char status;
+	unsigned long flags;
+	u8 iir;
+	int dma_err = 0;
+
+	serial8250_rpm_get(up);
+
+	iir = serial_port_in(port, UART_IIR);
+	if (iir & UART_IIR_NO_INT) {
+		serial8250_rpm_put(up);
+		return 0;
+	}
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	status = serial_port_in(port, UART_LSR);
+
+	if (status & (UART_LSR_DR | UART_LSR_BI)) {
+
+		dma_err = omap_8250_rx_dma(up, iir);
+		if (dma_err) {
+			status = serial8250_rx_chars(up, status);
+			omap_8250_rx_dma(up, 0);
+		}
+	}
+	serial8250_modem_status(up);
+	if (status & UART_LSR_THRE && up->dma->tx_err) {
+		if (uart_tx_stopped(&up->port) ||
+		    uart_circ_empty(&up->port.state->xmit)) {
+			up->dma->tx_err = 0;
+			serial8250_tx_chars(up);
+		} else  {
+			/*
+			 * try again due to an earlier failer which
+			 * might have been resolved by now.
+			 */
+			dma_err = omap_8250_tx_dma(up);
+			if (dma_err)
+				serial8250_tx_chars(up);
+		}
+	}
+
+	spin_unlock_irqrestore(&port->lock, flags);
+	serial8250_rpm_put(up);
+	return 1;
+}
 #endif
 
 static int omap8250_probe(struct platform_device *pdev)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 13/13] tty: serial: 8250: omap: add dma support
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (11 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 12/13] tty: serial: 8250: omap: add custom irq handling Sebastian Andrzej Siewior
@ 2014-09-29 18:06 ` Sebastian Andrzej Siewior
  2014-10-02 16:43 ` [PATCH 00/13 v10] omap 8250 based UART + DMA Tony Lindgren
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-09-29 18:06 UTC (permalink / raw)
  To: linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	Sebastian Andrzej Siewior

This patch adds the required pieces to 8250-OMAP UART driver for DMA
support. The TX burst size is set to 1 so we can send an arbitrary
amount of bytes.

The RX burst is currently set to 48 which means we receive an DMA
interrupt every 48 bytes and have to reprogram everything. Less bytes in
the RX-FIFO mean that no DMA transfer will happen and the UART will send a
RX-timeout _or_ RDI event at which point the FIFO will be manually purged.
There is a workaround for TX-DMA on AM33xx where we put the first byte
into the FIFO to kick start the DMA process. Haven't seen this problem on
OMAP36xx (beagle board xm) or DRA7xx.

On AM375x there is "Usage Note 2.7: UART: Cannot Acknowledge Idle
Requests in Smartidle Mode When Configured for DMA Operations" in the
errata document. This problem persists even after disabling DMA in the
UART and will be addressed in the HWMOD.

v10:
	- delay update_registers() from set_termios() until TX-DMA is
	  done. It has been reported / proved that invoking
	  update_registers() while TX-DMA is in progress may stall the
	  DMA operation and it won't finish.
	- use the new omap DMA-TX-RX hooks and DMA only interrupt
	  routine.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_omap.c | 71 +++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 6500547f8fda..57a8b1241b85 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -88,6 +88,7 @@ struct omap8250_priv {
 	u8 wer;
 	u8 xon;
 	u8 xoff;
+	u8 delayed_restore;
 	u16 quot;
 
 	bool is_suspending;
@@ -211,6 +212,18 @@ static void omap8250_update_scr(struct uart_8250_port *up,
 static void omap8250_restore_regs(struct uart_8250_port *up)
 {
 	struct omap8250_priv *priv = up->port.private_data;
+	struct uart_8250_dma	*dma = up->dma;
+
+	if (dma && dma->tx_running) {
+		/*
+		 * TCSANOW requests the change to occur immediately however if
+		 * we have a TX-DMA operation in progress then it has been
+		 * observed that it might stall and never complete. Therefore we
+		 * delay DMA completes to prevent this hang from happen.
+		 */
+		priv->delayed_restore = 1;
+		return;
+	}
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_EFR, UART_EFR_ECB);
@@ -375,6 +388,10 @@ static void omap_8250_set_termios(struct uart_port *port,
 	priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY |
 		OMAP_UART_SCR_TX_TRIG_GRANU1_MASK;
 
+	if (up->dma)
+		priv->scr |= OMAP_UART_SCR_DMAMODE_1 |
+			OMAP_UART_SCR_DMAMODE_CTL;
+
 	priv->xon = termios->c_cc[VSTART];
 	priv->xoff = termios->c_cc[VSTOP];
 
@@ -554,6 +571,9 @@ static int omap_8250_startup(struct uart_port *port)
 		priv->wer |= OMAP_UART_TX_WAKEUP_EN;
 	serial_out(up, UART_OMAP_WER, priv->wer);
 
+	if (up->dma)
+		up->dma->rx_dma(up, 0);
+
 	pm_runtime_mark_last_busy(port->dev);
 	pm_runtime_put_autosuspend(port->dev);
 	return 0;
@@ -572,6 +592,8 @@ static void omap_8250_shutdown(struct uart_port *port)
 	struct omap8250_priv *priv = port->private_data;
 
 	flush_work(&priv->qos_work);
+	if (up->dma)
+		up->dma->rx_dma(up, UART_IIR_RX_TIMEOUT);
 
 	pm_runtime_get_sync(port->dev);
 
@@ -725,6 +747,7 @@ static void omap_8250_dma_tx_complete(void *param)
 	struct circ_buf		*xmit = &p->port.state->xmit;
 	unsigned long		flags;
 	bool			en_thri = false;
+	struct omap8250_priv	*priv = p->port.private_data;
 
 	dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
@@ -737,6 +760,11 @@ static void omap_8250_dma_tx_complete(void *param)
 	xmit->tail &= UART_XMIT_SIZE - 1;
 	p->port.icount.tx += dma->tx_size;
 
+	if (priv->delayed_restore) {
+		priv->delayed_restore = 0;
+		omap8250_restore_regs(p);
+	}
+
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&p->port);
 
@@ -909,6 +937,18 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
 	serial8250_rpm_put(up);
 	return 1;
 }
+
+static bool the_no_dma_filter_fn(struct dma_chan *chan, void *param)
+{
+	return false;
+}
+
+#else
+
+static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
+{
+	return -EINVAL;
+}
 #endif
 
 static int omap8250_probe(struct platform_device *pdev)
@@ -1010,6 +1050,32 @@ static int omap8250_probe(struct platform_device *pdev)
 	pm_runtime_get_sync(&pdev->dev);
 
 	omap_serial_fill_features_erratas(&up, priv);
+#ifdef CONFIG_SERIAL_8250_DMA
+	if (pdev->dev.of_node) {
+		/*
+		 * Oh DMA support. If there are no DMA properties in the DT then
+		 * we will fall back to a generic DMA channel which does not
+		 * really work here. To ensure that we do not get a generic DMA
+		 * channel assigned, we have the the_no_dma_filter_fn() here.
+		 * To avoid "failed to request DMA" messages we check for DMA
+		 * properties in DT.
+		 */
+		ret = of_property_count_strings(pdev->dev.of_node, "dma-names");
+		if (ret == 2) {
+			up.dma = &priv->omap8250_dma;
+			up.port.handle_irq = omap_8250_dma_handle_irq;
+			priv->omap8250_dma.fn = the_no_dma_filter_fn;
+			priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
+			priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
+			priv->omap8250_dma.rx_size = RX_TRIGGER;
+			priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
+			priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
+
+			if (of_machine_is_compatible("ti,am33xx"))
+				priv->habit |= OMAP_DMA_TX_KICK;
+		}
+	}
+#endif
 	ret = serial8250_register_8250_port(&up);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "unable to register 8250 port\n");
@@ -1146,6 +1212,8 @@ static int omap8250_runtime_suspend(struct device *dev)
 	}
 
 	omap8250_enable_wakeup(priv, true);
+	if (up->dma)
+		omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
 
 	priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
 	schedule_work(&priv->qos_work);
@@ -1170,6 +1238,9 @@ static int omap8250_runtime_resume(struct device *dev)
 	if (loss_cntx)
 		omap8250_restore_regs(up);
 
+	if (up->dma)
+		omap_8250_rx_dma(up, 0);
+
 	priv->latency = priv->calc_latency;
 	schedule_work(&priv->qos_work);
 	return 0;
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH 02/13] tty: serial: 8250: make serial8250_console_setup() non _init
  2014-09-29 18:06 ` [PATCH 02/13] tty: serial: 8250: make serial8250_console_setup() non _init Sebastian Andrzej Siewior
@ 2014-09-30 20:27   ` Peter Hurley
  0 siblings, 0 replies; 41+ messages in thread
From: Peter Hurley @ 2014-09-30 20:27 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh

On 09/29/2014 02:06 PM, Sebastian Andrzej Siewior wrote:
> if I boot with console=ttyS0 and the omap driver is module I end up with
> 
> | console [ttyS0] disabled

Note to self: make ISA config optional.

> | omap8250 44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 88, base_baud = 3000000) is a 8250
> | Unable to handle kernel paging request at virtual address c07a9de0
> | Modules linked in: 8250_omap(+)
> | CPU: 0 PID: 908 Comm: modprobe Not tainted 3.17.0-rc5+ #1593
> | PC is at serial8250_console_setup+0x0/0xc8
> | LR is at register_console+0x13c/0x3a4
> | [<c0078788>] (register_console) from [<c02d0340>] (uart_add_one_port+0x3cc/0x420)
> | [<c02d0340>] (uart_add_one_port) from [<c02d38a4>] (serial8250_register_8250_port+0x298/0x39c)
> | [<c02d38a4>] (serial8250_register_8250_port) from [<bf006274>] (omap8250_probe+0x218/0x3dc [8250_omap])
> | [<bf006274>] (omap8250_probe [8250_omap]) from [<c02e3424>] (platform_drv_probe+0x2c/0x5c)
> | [<c02e3424>] (platform_drv_probe) from [<c02e1eac>] (driver_probe_device+0x104/0x228)
> …
> | [<c009fa48>] (SyS_init_module) from [<c000e6e0>] (ret_fast_syscall+0x0/0x30)
> | Code: 7823603b f8314620 051b3013 491ed416 (44792204)
> 
> because serial8250_console_setup() is already gone.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Reviewed-by: Peter Hurley <peter@hurleysoftware.com>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause()
  2014-09-29 18:06 ` [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause() Sebastian Andrzej Siewior
@ 2014-10-01 12:00   ` Peter Ujfalusi
  2014-10-15 15:27   ` Vinod Koul
  2014-10-15 15:28   ` Vinod Koul
  2 siblings, 0 replies; 41+ messages in thread
From: Peter Ujfalusi @ 2014-10-01 12:00 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh,
	vinod.koul

On 09/29/2014 09:06 PM, Sebastian Andrzej Siewior wrote:
> I added book keeping of whether or not the 8250-dma driver has an RX
> transfer pending or not so we don't BUG here if it calls
> dmaengine_pause() on a channel which has not a pending transfer. Guess
> what, this is not enough.
> The following can be triggered with a busy RX channel and hackbench in
> background:
> - DMA transfer completes. The callback is delayed via
>   vchan_cookie_complete() into a tasklet so it das not happen asap.
> - hackbench keeps the system busy so the tasklet does not run "soon".
> - the UART collected enough data and generates an "timeout"-interrupt.
>   Since 8250-dma *thinks* the DMA-transfer is still pending it tries to
>   cancel it via invoking dmaengine_pause() first. This causes the segfault
>   because echan->edesc is NULL now that the transfer completed (however
>   the callback did not run yet).
> 
> With this patch we don't BUG in the scenario described.

Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>

> 
> Cc: vinod.koul@intel.com
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  drivers/dma/edma.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
> index 7b65633f495e..123f578d6dd3 100644
> --- a/drivers/dma/edma.c
> +++ b/drivers/dma/edma.c
> @@ -288,7 +288,7 @@ static int edma_slave_config(struct edma_chan *echan,
>  static int edma_dma_pause(struct edma_chan *echan)
>  {
>  	/* Pause/Resume only allowed with cyclic mode */
> -	if (!echan->edesc->cyclic)
> +	if (!echan->edesc || !echan->edesc->cyclic)
>  		return -EINVAL;
>  
>  	edma_pause(echan->ch_num);
> 


-- 
Péter

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/13 v10] omap 8250 based UART + DMA
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (12 preceding siblings ...)
  2014-09-29 18:06 ` [PATCH 13/13] tty: serial: 8250: omap: add dma support Sebastian Andrzej Siewior
@ 2014-10-02 16:43 ` Tony Lindgren
  2014-10-02 23:19   ` Sebastian Andrzej Siewior
  2014-10-03 13:08 ` Peter Hurley
  2014-11-06  3:14 ` Greg KH
  15 siblings, 1 reply; 41+ messages in thread
From: Tony Lindgren @ 2014-10-02 16:43 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, balbi, gregkh

* Sebastian Andrzej Siewior <bigeasy@linutronix.de> [140929 11:07]:
> The queue is getting smaller. The highlights of v9…v10
> - the DMA stall Frans Klaver reported which popped up in yocto is gone. It
>   also seems that the "ack the err-irq even if nothing happened" in EDMA
>   can be dropped.
> - the RX- and TX-DMA callbacks are now OMAP-only and no "bugs" flags are
>   introduced into the generic DMA code. This also means that there is
>   custom IRQ routine in case of DMA.

Looks good to me. For the patches that do not yet have my acks, please
feel free to add:

Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>

It's probably best that I queue the .dts changes separately though
to avoid pointless merge conflicts.

Regards,

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/13 v10] omap 8250 based UART + DMA
  2014-10-02 16:43 ` [PATCH 00/13 v10] omap 8250 based UART + DMA Tony Lindgren
@ 2014-10-02 23:19   ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-10-02 23:19 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, balbi, gregkh

* Tony Lindgren | 2014-10-02 09:43:39 [-0700]:

>Looks good to me. For the patches that do not yet have my acks, please
>feel free to add:
>
>Reviewed-by: Tony Lindgren <tony@atomide.com>
>Tested-by: Tony Lindgren <tony@atomide.com>
Thanks.

>It's probably best that I queue the .dts changes separately though
>to avoid pointless merge conflicts.

Yeah. There is no real dependency on them except that you need them at
some point :)

>Regards,
>
>Tony

Sebastian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/13 v10] omap 8250 based UART + DMA
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (13 preceding siblings ...)
  2014-10-02 16:43 ` [PATCH 00/13 v10] omap 8250 based UART + DMA Tony Lindgren
@ 2014-10-03 13:08 ` Peter Hurley
  2014-11-06  3:14 ` Greg KH
  15 siblings, 0 replies; 41+ messages in thread
From: Peter Hurley @ 2014-10-03 13:08 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, linux-serial
  Cc: linux-kernel, linux-omap, linux-arm-kernel, tony, balbi, gregkh

On 09/29/2014 02:06 PM, Sebastian Andrzej Siewior wrote:
> The queue is getting smaller. The highlights of v9…v10
> - the DMA stall Frans Klaver reported which popped up in yocto is gone. It
>   also seems that the "ack the err-irq even if nothing happened" in EDMA
>   can be dropped.
> - the RX- and TX-DMA callbacks are now OMAP-only and no "bugs" flags are
>   introduced into the generic DMA code. This also means that there is
>   custom IRQ routine in case of DMA.

For the series:

Reviewed-by: Peter Hurley <peter@hurleysoftware.com>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 12/13] tty: serial: 8250: omap: add custom irq handling
  2014-09-29 18:06 ` [PATCH 12/13] tty: serial: 8250: omap: add custom irq handling Sebastian Andrzej Siewior
@ 2014-10-09 13:19   ` Heikki Krogerus
  0 siblings, 0 replies; 41+ messages in thread
From: Heikki Krogerus @ 2014-10-09 13:19 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, Peter Hurley

On Mon, Sep 29, 2014 at 08:06:48PM +0200, Sebastian Andrzej Siewior wrote:
> We have (or will have) custom DMA callbacks in the omap driver due to
> the different behaviour in the RX and TX case. To make this work
> we need a few changes in the IRQ handler to invoke the rx_handler again
> after the "manual" mode or retry the tx_handler again before falling
> back to the manual mode.
> 
> Heikki didn't want to see the extra hacks in the generic / default irq
> handler and Peter wasn't too happy about an OMAP-only IRQ handler. The
> way I planned it is to use this extra IRQ routine only in DMA case. If
> Peter dislike this approach then I hope Heikki doesn't block changes in
> the default IRQ handler :)
> 
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Peter Hurley <peter@hurleysoftware.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Looks good to me.

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>


-- 
heikki

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause()
  2014-09-29 18:06 ` [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause() Sebastian Andrzej Siewior
  2014-10-01 12:00   ` Peter Ujfalusi
@ 2014-10-15 15:27   ` Vinod Koul
  2014-10-15 15:28   ` Vinod Koul
  2 siblings, 0 replies; 41+ messages in thread
From: Vinod Koul @ 2014-10-15 15:27 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh

On Mon, Sep 29, 2014 at 08:06:45PM +0200, Sebastian Andrzej Siewior wrote:
> I added book keeping of whether or not the 8250-dma driver has an RX
> transfer pending or not so we don't BUG here if it calls
> dmaengine_pause() on a channel which has not a pending transfer. Guess
> what, this is not enough.
> The following can be triggered with a busy RX channel and hackbench in
> background:
> - DMA transfer completes. The callback is delayed via
>   vchan_cookie_complete() into a tasklet so it das not happen asap.
> - hackbench keeps the system busy so the tasklet does not run "soon".
> - the UART collected enough data and generates an "timeout"-interrupt.
>   Since 8250-dma *thinks* the DMA-transfer is still pending it tries to
>   cancel it via invoking dmaengine_pause() first. This causes the segfault
>   because echan->edesc is NULL now that the transfer completed (however
>   the callback did not run yet).
> 
> With this patch we don't BUG in the scenario described.

Applied thanks

-- 
~Vinod
> 
> Cc: vinod.koul@intel.com
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  drivers/dma/edma.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
> index 7b65633f495e..123f578d6dd3 100644
> --- a/drivers/dma/edma.c
> +++ b/drivers/dma/edma.c
> @@ -288,7 +288,7 @@ static int edma_slave_config(struct edma_chan *echan,
>  static int edma_dma_pause(struct edma_chan *echan)
>  {
>  	/* Pause/Resume only allowed with cyclic mode */
> -	if (!echan->edesc->cyclic)
> +	if (!echan->edesc || !echan->edesc->cyclic)
>  		return -EINVAL;
>  
>  	edma_pause(echan->ch_num);
> -- 
> 2.1.0
> 

-- 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause()
  2014-09-29 18:06 ` [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause() Sebastian Andrzej Siewior
  2014-10-01 12:00   ` Peter Ujfalusi
  2014-10-15 15:27   ` Vinod Koul
@ 2014-10-15 15:28   ` Vinod Koul
  2 siblings, 0 replies; 41+ messages in thread
From: Vinod Koul @ 2014-10-15 15:28 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh

On Mon, Sep 29, 2014 at 08:06:45PM +0200, Sebastian Andrzej Siewior wrote:
> I added book keeping of whether or not the 8250-dma driver has an RX
> transfer pending or not so we don't BUG here if it calls
> dmaengine_pause() on a channel which has not a pending transfer. Guess
> what, this is not enough.
> The following can be triggered with a busy RX channel and hackbench in
> background:
> - DMA transfer completes. The callback is delayed via
>   vchan_cookie_complete() into a tasklet so it das not happen asap.
> - hackbench keeps the system busy so the tasklet does not run "soon".
> - the UART collected enough data and generates an "timeout"-interrupt.
>   Since 8250-dma *thinks* the DMA-transfer is still pending it tries to
>   cancel it via invoking dmaengine_pause() first. This causes the segfault
>   because echan->edesc is NULL now that the transfer completed (however
>   the callback did not run yet).
> 
> With this patch we don't BUG in the scenario described.

Applied, thanks

-- 
~Vinod

> 
> Cc: vinod.koul@intel.com
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  drivers/dma/edma.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
> index 7b65633f495e..123f578d6dd3 100644
> --- a/drivers/dma/edma.c
> +++ b/drivers/dma/edma.c
> @@ -288,7 +288,7 @@ static int edma_slave_config(struct edma_chan *echan,
>  static int edma_dma_pause(struct edma_chan *echan)
>  {
>  	/* Pause/Resume only allowed with cyclic mode */
> -	if (!echan->edesc->cyclic)
> +	if (!echan->edesc || !echan->edesc->cyclic)
>  		return -EINVAL;
>  
>  	edma_pause(echan->ch_num);
> -- 
> 2.1.0
> 

-- 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-09-29 18:06 ` [PATCH 11/13] arm: dts: dra7: " Sebastian Andrzej Siewior
@ 2014-11-04 17:02   ` Lennart Sorensen
  2014-11-04 17:06     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-04 17:02 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Mon, Sep 29, 2014 at 08:06:47PM +0200, Sebastian Andrzej Siewior wrote:
> Cc: devicetree@vger.kernel.org
> Reviewed-by: Tony Lindgren <tony@atomide.com>
> Tested-by: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  arch/arm/boot/dts/dra7.dtsi | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
> index d678152db4cb..f273e3811f75 100644
> --- a/arch/arm/boot/dts/dra7.dtsi
> +++ b/arch/arm/boot/dts/dra7.dtsi
> @@ -332,6 +332,8 @@
>  			ti,hwmods = "uart1";
>  			clock-frequency = <48000000>;
>  			status = "disabled";
> +			dmas = <&sdma 49>, <&sdma 50>;
> +			dma-names = "tx", "rx";
>  		};
>  
>  		uart2: serial@4806c000 {
> @@ -341,6 +343,8 @@
>  			ti,hwmods = "uart2";
>  			clock-frequency = <48000000>;
>  			status = "disabled";
> +			dmas = <&sdma 51>, <&sdma 52>;
> +			dma-names = "tx", "rx";
>  		};
>  
>  		uart3: serial@48020000 {
> @@ -350,6 +354,8 @@
>  			ti,hwmods = "uart3";
>  			clock-frequency = <48000000>;
>  			status = "disabled";
> +			dmas = <&sdma 53>, <&sdma 54>;
> +			dma-names = "tx", "rx";
>  		};
>  
>  		uart4: serial@4806e000 {
> @@ -359,6 +365,8 @@
>  			ti,hwmods = "uart4";
>  			clock-frequency = <48000000>;
>                          status = "disabled";
> +			dmas = <&sdma 55>, <&sdma 56>;
> +			dma-names = "tx", "rx";
>  		};
>  
>  		uart5: serial@48066000 {
> @@ -368,6 +376,8 @@
>  			ti,hwmods = "uart5";
>  			clock-frequency = <48000000>;
>  			status = "disabled";
> +			dmas = <&sdma 63>, <&sdma 64>;
> +			dma-names = "tx", "rx";
>  		};
>  
>  		uart6: serial@48068000 {
> @@ -377,6 +387,8 @@
>  			ti,hwmods = "uart6";
>  			clock-frequency = <48000000>;
>  			status = "disabled";
> +			dmas = <&sdma 79>, <&sdma 80>;
> +			dma-names = "tx", "rx";
>  		};
>  
>  		uart7: serial@48420000 {

According to the manual the DMA channels for UART7 to 10 are:

uart7:  144 145
uart8:  146 147
uart9:  148 149
uart10: 150 151

Might as well add those too.  We have uart 7 and 8 in use on our board
so I am about to go test it.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 17:02   ` Lennart Sorensen
@ 2014-11-04 17:06     ` Sebastian Andrzej Siewior
  2014-11-04 17:21       ` Lennart Sorensen
  0 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-11-04 17:06 UTC (permalink / raw)
  To: Lennart Sorensen
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On 11/04/2014 06:02 PM, Lennart Sorensen wrote:
> 
> According to the manual the DMA channels for UART7 to 10 are:
> 
> uart7:  144 145
> uart8:  146 147
> uart9:  148 149
> uart10: 150 151
> 
> Might as well add those too.  We have uart 7 and 8 in use on our board
> so I am about to go test it.

Mind sharing the manual with me? Mine does not mention DMA channels for
UART7-10. If you are able to test 7+8 (and it works) could you please
make patch which with for the remaining four devices?

Sebastian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 17:06     ` Sebastian Andrzej Siewior
@ 2014-11-04 17:21       ` Lennart Sorensen
  2014-11-04 18:32         ` Javier Martinez Canillas
  2014-11-04 18:33         ` Lennart Sorensen
  0 siblings, 2 replies; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-04 17:21 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Tue, Nov 04, 2014 at 06:06:37PM +0100, Sebastian Andrzej Siewior wrote:
> On 11/04/2014 06:02 PM, Lennart Sorensen wrote:
> > 
> > According to the manual the DMA channels for UART7 to 10 are:
> > 
> > uart7:  144 145
> > uart8:  146 147
> > uart9:  148 149
> > uart10: 150 151
> > 
> > Might as well add those too.  We have uart 7 and 8 in use on our board
> > so I am about to go test it.
> 
> Mind sharing the manual with me? Mine does not mention DMA channels for
> UART7-10. If you are able to test 7+8 (and it works) could you please
> make patch which with for the remaining four devices?

Well the file I have is called AM572x_ES1.1_NDA_TRM_vT.pdf, so I am not
sure who I am allowed to share that file with.  Might be simpler to just
ask TI for the latest version.

How I hate NDAs.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 17:21       ` Lennart Sorensen
@ 2014-11-04 18:32         ` Javier Martinez Canillas
  2014-11-04 18:48           ` Nishanth Menon
  2014-11-04 19:00           ` Lennart Sorensen
  2014-11-04 18:33         ` Lennart Sorensen
  1 sibling, 2 replies; 41+ messages in thread
From: Javier Martinez Canillas @ 2014-11-04 18:32 UTC (permalink / raw)
  To: Lennart Sorensen
  Cc: Sebastian Andrzej Siewior, linux-serial, Linux Kernel,
	linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	Greg Kroah-Hartman, devicetree

Hello,

On Tue, Nov 4, 2014 at 6:21 PM, Lennart Sorensen
<lsorense@csclub.uwaterloo.ca> wrote:
>> Mind sharing the manual with me? Mine does not mention DMA channels for
>> UART7-10. If you are able to test 7+8 (and it works) could you please
>> make patch which with for the remaining four devices?
>
> Well the file I have is called AM572x_ES1.1_NDA_TRM_vT.pdf, so I am not
> sure who I am allowed to share that file with.  Might be simpler to just
> ask TI for the latest version.
>
> How I hate NDAs.
>

I saw today an announcement about a public AM572x Silicon Revision 1.1
TRM [0] that has just made available by TI. I'm not familiar with this
SoC so I don't know if that has the information you want but I thought
it was worth to mention in case it did.

Best regards,
Javier

[0]: http://www.ti.com/lit/ug/spruhz6/spruhz6.pdf

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 17:21       ` Lennart Sorensen
  2014-11-04 18:32         ` Javier Martinez Canillas
@ 2014-11-04 18:33         ` Lennart Sorensen
  2014-11-04 21:03           ` Lennart Sorensen
  1 sibling, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-04 18:33 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Tue, Nov 04, 2014 at 12:21:17PM -0500, Lennart Sorensen wrote:
> Well the file I have is called AM572x_ES1.1_NDA_TRM_vT.pdf, so I am not
> sure who I am allowed to share that file with.  Might be simpler to just
> ask TI for the latest version.
> 
> How I hate NDAs.

Well it doesn't work, because I don't have the dma croassbar patches
from ti-linux-3.14.y which are required to use the full range of dma
channels on the dra7.

I will see how well it works without dma at least.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 18:32         ` Javier Martinez Canillas
@ 2014-11-04 18:48           ` Nishanth Menon
  2014-11-04 19:00           ` Lennart Sorensen
  1 sibling, 0 replies; 41+ messages in thread
From: Nishanth Menon @ 2014-11-04 18:48 UTC (permalink / raw)
  To: Javier Martinez Canillas, Lennart Sorensen
  Cc: Sebastian Andrzej Siewior, linux-serial, Linux Kernel,
	linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	Greg Kroah-Hartman, devicetree

On 11/04/2014 12:32 PM, Javier Martinez Canillas wrote:
> Hello,
> 
> On Tue, Nov 4, 2014 at 6:21 PM, Lennart Sorensen
> <lsorense@csclub.uwaterloo.ca> wrote:
>>> Mind sharing the manual with me? Mine does not mention DMA channels for
>>> UART7-10. If you are able to test 7+8 (and it works) could you please
>>> make patch which with for the remaining four devices?
>>
>> Well the file I have is called AM572x_ES1.1_NDA_TRM_vT.pdf, so I am not
>> sure who I am allowed to share that file with.  Might be simpler to just
>> ask TI for the latest version.
>>
>> How I hate NDAs.
>>
> 
> I saw today an announcement about a public AM572x Silicon Revision 1.1
> TRM [0] that has just made available by TI. I'm not familiar with this
> SoC so I don't know if that has the information you want but I thought
> it was worth to mention in case it did.
> 
> Best regards,
> Javier
> 
> [0]: http://www.ti.com/lit/ug/spruhz6/spruhz6.pdf

Same chip.


-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 18:32         ` Javier Martinez Canillas
  2014-11-04 18:48           ` Nishanth Menon
@ 2014-11-04 19:00           ` Lennart Sorensen
  1 sibling, 0 replies; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-04 19:00 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Sebastian Andrzej Siewior, linux-serial, Linux Kernel,
	linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	Greg Kroah-Hartman, devicetree

On Tue, Nov 04, 2014 at 07:32:07PM +0100, Javier Martinez Canillas wrote:
> Hello,
> 
> On Tue, Nov 4, 2014 at 6:21 PM, Lennart Sorensen
> <lsorense@csclub.uwaterloo.ca> wrote:
> >> Mind sharing the manual with me? Mine does not mention DMA channels for
> >> UART7-10. If you are able to test 7+8 (and it works) could you please
> >> make patch which with for the remaining four devices?
> >
> > Well the file I have is called AM572x_ES1.1_NDA_TRM_vT.pdf, so I am not
> > sure who I am allowed to share that file with.  Might be simpler to just
> > ask TI for the latest version.
> >
> > How I hate NDAs.
> >
> 
> I saw today an announcement about a public AM572x Silicon Revision 1.1
> TRM [0] that has just made available by TI. I'm not familiar with this
> SoC so I don't know if that has the information you want but I thought
> it was worth to mention in case it did.
> 
> Best regards,
> Javier
> 
> [0]: http://www.ti.com/lit/ug/spruhz6/spruhz6.pdf

That's the right one.

Page 3622 has the dma channels for uart 7 through 10, but it still needs
the updated crossbar dma driver to work.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 18:33         ` Lennart Sorensen
@ 2014-11-04 21:03           ` Lennart Sorensen
  2014-11-05  1:15             ` Lennart Sorensen
  0 siblings, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-04 21:03 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Tue, Nov 04, 2014 at 01:33:15PM -0500, Lennart Sorensen wrote:
> Well it doesn't work, because I don't have the dma croassbar patches
> from ti-linux-3.14.y which are required to use the full range of dma
> channels on the dra7.
> 
> I will see how well it works without dma at least.

So it seems to be working on our board so far.  Will stress test it
some more.  No DMA of course for now, but oh well.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-04 21:03           ` Lennart Sorensen
@ 2014-11-05  1:15             ` Lennart Sorensen
  2014-11-05  8:11               ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-05  1:15 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Tue, Nov 04, 2014 at 04:03:15PM -0500, Lennart Sorensen wrote:
> So it seems to be working on our board so far.  Will stress test it
> some more.  No DMA of course for now, but oh well.

Well 4 hours running with multiple reboots (our testsuite reboots every
30 minutes to test the watchdog).  So far it has only lost 70 bytes out
of 40MB of data sent between uart7 and uart8 (and we are pretty sure
the serial test has a small bug that causes a few bytes to be lost right
after a reboot sometimes).

The reason I am even trying the new driver today is that we were seeing
soft lockups on the CPU whenever the serial ports were being tested,
usually in less than 5 minutes, so 4 hours without a lockup is a good
sign.  No idea what might be wrong with the old omap serial driver, but
it seems something is (unless of course we managed to break it somehow
when we tried to solve its habit of dropping characters).

I think I will stick with this new driver.  Better long term future
anyhow.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-05  1:15             ` Lennart Sorensen
@ 2014-11-05  8:11               ` Sebastian Andrzej Siewior
  2014-11-05 15:33                 ` Lennart Sorensen
  0 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-11-05  8:11 UTC (permalink / raw)
  To: Lennart Sorensen
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On 11/05/2014 02:15 AM, Lennart Sorensen wrote:
> Well 4 hours running with multiple reboots (our testsuite reboots every
> 30 minutes to test the watchdog).  So far it has only lost 70 bytes out
> of 40MB of data sent between uart7 and uart8 (and we are pretty sure
> the serial test has a small bug that causes a few bytes to be lost right
> after a reboot sometimes).
> 
> The reason I am even trying the new driver today is that we were seeing
> soft lockups on the CPU whenever the serial ports were being tested,
> usually in less than 5 minutes, so 4 hours without a lockup is a good
> sign.  No idea what might be wrong with the old omap serial driver, but
> it seems something is (unless of course we managed to break it somehow
> when we tried to solve its habit of dropping characters).

Okay. No DMA but the basic part seems to work for you. Thanks for
testing.

Sebastian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-05  8:11               ` Sebastian Andrzej Siewior
@ 2014-11-05 15:33                 ` Lennart Sorensen
  2014-11-05 16:20                   ` Lennart Sorensen
  0 siblings, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-05 15:33 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Wed, Nov 05, 2014 at 09:11:35AM +0100, Sebastian Andrzej Siewior wrote:
> Okay. No DMA but the basic part seems to work for you. Thanks for
> testing.

Two systems ran 16 hours each so far with no issues.  Pushed 170MB of
data through the pair of serial ports on one system at 230400.

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-05 15:33                 ` Lennart Sorensen
@ 2014-11-05 16:20                   ` Lennart Sorensen
  2014-11-05 16:30                     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-05 16:20 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Wed, Nov 05, 2014 at 10:33:15AM -0500, Lennart Sorensen wrote:
> Two systems ran 16 hours each so far with no issues.  Pushed 170MB of
> data through the pair of serial ports on one system at 230400.

The console on uart3 doesn't appear to be using the dma assuming the
values in /sys for the dma controller and bytes transferred mean anything.
It does mention in dmesg that it allocated dma channels for uart3 though.

How do you tell if it is using dma?

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-05 16:20                   ` Lennart Sorensen
@ 2014-11-05 16:30                     ` Sebastian Andrzej Siewior
  2014-11-05 19:43                       ` Lennart Sorensen
  0 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-11-05 16:30 UTC (permalink / raw)
  To: Lennart Sorensen
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On 11/05/2014 05:20 PM, Lennart Sorensen wrote:
> On Wed, Nov 05, 2014 at 10:33:15AM -0500, Lennart Sorensen wrote:
>> Two systems ran 16 hours each so far with no issues.  Pushed 170MB of
>> data through the pair of serial ports on one system at 230400.
> 
> The console on uart3 doesn't appear to be using the dma assuming the
> values in /sys for the dma controller and bytes transferred mean anything.
> It does mention in dmesg that it allocated dma channels for uart3 though.

Then it should use it :)

> How do you tell if it is using dma?

There is omap_8250_tx_dma() and omap_8250_rx_dma(). Both setup
callbacks (the rx+tx _complete). Upon successful DMA transfer you
should see them invoked with bytes transfered (>0).
For RX transfer you need at least trigger bytes in the FIFO within a
given time frame (I think it was 46 bytes and the delay may be up to 2
bytes). If you miss this then DMA for RX won't wire and you purge the
FIFO manually via "timeout-interrupt" (the callback will be invoked
with an error condition and 0 bytes).

Assuming this works for you then one should figure out why the counters
in /sys are not updated…

Sebastian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-05 16:30                     ` Sebastian Andrzej Siewior
@ 2014-11-05 19:43                       ` Lennart Sorensen
  2014-11-13 18:34                         ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-05 19:43 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Wed, Nov 05, 2014 at 05:30:51PM +0100, Sebastian Andrzej Siewior wrote:
> On 11/05/2014 05:20 PM, Lennart Sorensen wrote:
> > On Wed, Nov 05, 2014 at 10:33:15AM -0500, Lennart Sorensen wrote:
> >> Two systems ran 16 hours each so far with no issues.  Pushed 170MB of
> >> data through the pair of serial ports on one system at 230400.
> > 
> > The console on uart3 doesn't appear to be using the dma assuming the
> > values in /sys for the dma controller and bytes transferred mean anything.
> > It does mention in dmesg that it allocated dma channels for uart3 though.
> 
> Then it should use it :)

I managed to get something dma related on uart3.  But it isn't happy:

[   95.577401] DMA misaligned error with device 53
repeated many times.

I wonder if the dma support isn't quite working for the omap572x yet in
this tree (ti's 3.12.y tree), or maybe it is picky and the driver still
needs a bit of work.

I have had no issues on uart7 and 8 without dma.

> There is omap_8250_tx_dma() and omap_8250_rx_dma(). Both setup
> callbacks (the rx+tx _complete). Upon successful DMA transfer you
> should see them invoked with bytes transfered (>0).
> For RX transfer you need at least trigger bytes in the FIFO within a
> given time frame (I think it was 46 bytes and the delay may be up to 2
> bytes). If you miss this then DMA for RX won't wire and you purge the
> FIFO manually via "timeout-interrupt" (the callback will be invoked
> with an error condition and 0 bytes).
> 
> Assuming this works for you then one should figure out why the counters
> in /sys are not updated…

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/13 v10] omap 8250 based UART + DMA
  2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
                   ` (14 preceding siblings ...)
  2014-10-03 13:08 ` Peter Hurley
@ 2014-11-06  3:14 ` Greg KH
  2014-11-06 10:27   ` Sebastian Andrzej Siewior
  15 siblings, 1 reply; 41+ messages in thread
From: Greg KH @ 2014-11-06  3:14 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony, balbi

On Mon, Sep 29, 2014 at 08:06:36PM +0200, Sebastian Andrzej Siewior wrote:
> The queue is getting smaller. The highlights of v9…v10
> - the DMA stall Frans Klaver reported which popped up in yocto is gone. It
>   also seems that the "ack the err-irq even if nothing happened" in EDMA
>   can be dropped.
> - the RX- and TX-DMA callbacks are now OMAP-only and no "bugs" flags are
>   introduced into the generic DMA code. This also means that there is
>   custom IRQ routine in case of DMA.

I've now applied the patches here that I could, if I have missed any,
please let me know and resend.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/13 v10] omap 8250 based UART + DMA
  2014-11-06  3:14 ` Greg KH
@ 2014-11-06 10:27   ` Sebastian Andrzej Siewior
  2014-11-10 17:24     ` Tony Lindgren
  0 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-11-06 10:27 UTC (permalink / raw)
  To: Greg KH, tony
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, balbi

On 11/06/2014 04:14 AM, Greg KH wrote:
> I've now applied the patches here that I could, if I have missed any,
> please let me know and resend.

Thank you Greg. I pulled your tty-testing and it seems to work on
am335x-evm/dra7-evm.

Tony, if you could please take the two .dts files then the series would
be complete (that one dma patch was applied by Vinod during the merge
window).

> 
> thanks,
> 
> greg k-h
> 
Sebastian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/13 v10] omap 8250 based UART + DMA
  2014-11-06 10:27   ` Sebastian Andrzej Siewior
@ 2014-11-10 17:24     ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2014-11-10 17:24 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Greg KH, linux-serial, linux-kernel, linux-omap, linux-arm-kernel, balbi

* Sebastian Andrzej Siewior <bigeasy@linutronix.de> [141106 02:29]:
> On 11/06/2014 04:14 AM, Greg KH wrote:
> > I've now applied the patches here that I could, if I have missed any,
> > please let me know and resend.
> 
> Thank you Greg. I pulled your tty-testing and it seems to work on
> am335x-evm/dra7-evm.
> 
> Tony, if you could please take the two .dts files then the series would
> be complete (that one dma patch was applied by Vinod during the merge
> window).

OK applying into omap-for-v3.19/dt thanks.

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-05 19:43                       ` Lennart Sorensen
@ 2014-11-13 18:34                         ` Sebastian Andrzej Siewior
  2014-11-13 22:08                           ` Lennart Sorensen
  0 siblings, 1 reply; 41+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-11-13 18:34 UTC (permalink / raw)
  To: Lennart Sorensen
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On 11/05/2014 08:43 PM, Lennart Sorensen wrote:
> I managed to get something dma related on uart3.  But it isn't happy:
> 
> [   95.577401] DMA misaligned error with device 53
> repeated many times.
> 
> I wonder if the dma support isn't quite working for the omap572x yet in
> this tree (ti's 3.12.y tree), or maybe it is picky and the driver still
> needs a bit of work.

misaligned dma? I haven't seen any alignment requirement for SDMA/EDMA
and I haven't seen this error on beagle board, am335x-evm or dra7-evm.

> I have had no issues on uart7 and 8 without dma.

So basically what you are saying is that DMA (no matter which channel)
gives you this error and without DMA it works fine?

Sebastian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] arm: dts: dra7: add DMA properties for UART
  2014-11-13 18:34                         ` Sebastian Andrzej Siewior
@ 2014-11-13 22:08                           ` Lennart Sorensen
  0 siblings, 0 replies; 41+ messages in thread
From: Lennart Sorensen @ 2014-11-13 22:08 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-serial, linux-kernel, linux-omap, linux-arm-kernel, tony,
	balbi, gregkh, devicetree

On Thu, Nov 13, 2014 at 07:34:09PM +0100, Sebastian Andrzej Siewior wrote:
> misaligned dma? I haven't seen any alignment requirement for SDMA/EDMA
> and I haven't seen this error on beagle board, am335x-evm or dra7-evm.

Well I am using the am5728, so it should be the same as the dra7-evm.

> So basically what you are saying is that DMA (no matter which channel)
> gives you this error and without DMA it works fine?

Yes.

I am trying to get the 3.14 kernel tree going, just as soon as I figure
out which config setting makes the timer probe not crash (it works
with the default config that enables every omap ever made, but I want
a cleaner build than that).

-- 
Len Sorensen

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2014-11-13 22:08 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-29 18:06 [PATCH 00/13 v10] omap 8250 based UART + DMA Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 01/13] tty: serial: 8250: Fix wording in runtime-PM comments Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 02/13] tty: serial: 8250: make serial8250_console_setup() non _init Sebastian Andrzej Siewior
2014-09-30 20:27   ` Peter Hurley
2014-09-29 18:06 ` [PATCH 03/13] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 04/13] tty: serial: 8250_dma: handle error on TX submit Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 05/13] tty: serial: 8250_dma: keep own book keeping about RX transfers Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 06/13] tty: serial: 8250: allow to use custom DMA implementation Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 07/13] tty: serial: 8250_omap: add custom DMA-TX callback Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 08/13] tty: serial: 8250_omap: add custom DMA-RX callback Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 09/13] dmaengine: edma: check for echan->edesc => NULL in edma_dma_pause() Sebastian Andrzej Siewior
2014-10-01 12:00   ` Peter Ujfalusi
2014-10-15 15:27   ` Vinod Koul
2014-10-15 15:28   ` Vinod Koul
2014-09-29 18:06 ` [PATCH 10/13] arm: dts: am33xx: add DMA properties for UART Sebastian Andrzej Siewior
2014-09-29 18:06 ` [PATCH 11/13] arm: dts: dra7: " Sebastian Andrzej Siewior
2014-11-04 17:02   ` Lennart Sorensen
2014-11-04 17:06     ` Sebastian Andrzej Siewior
2014-11-04 17:21       ` Lennart Sorensen
2014-11-04 18:32         ` Javier Martinez Canillas
2014-11-04 18:48           ` Nishanth Menon
2014-11-04 19:00           ` Lennart Sorensen
2014-11-04 18:33         ` Lennart Sorensen
2014-11-04 21:03           ` Lennart Sorensen
2014-11-05  1:15             ` Lennart Sorensen
2014-11-05  8:11               ` Sebastian Andrzej Siewior
2014-11-05 15:33                 ` Lennart Sorensen
2014-11-05 16:20                   ` Lennart Sorensen
2014-11-05 16:30                     ` Sebastian Andrzej Siewior
2014-11-05 19:43                       ` Lennart Sorensen
2014-11-13 18:34                         ` Sebastian Andrzej Siewior
2014-11-13 22:08                           ` Lennart Sorensen
2014-09-29 18:06 ` [PATCH 12/13] tty: serial: 8250: omap: add custom irq handling Sebastian Andrzej Siewior
2014-10-09 13:19   ` Heikki Krogerus
2014-09-29 18:06 ` [PATCH 13/13] tty: serial: 8250: omap: add dma support Sebastian Andrzej Siewior
2014-10-02 16:43 ` [PATCH 00/13 v10] omap 8250 based UART + DMA Tony Lindgren
2014-10-02 23:19   ` Sebastian Andrzej Siewior
2014-10-03 13:08 ` Peter Hurley
2014-11-06  3:14 ` Greg KH
2014-11-06 10:27   ` Sebastian Andrzej Siewior
2014-11-10 17:24     ` Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).