linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* (unknown), 
@ 2014-07-09 17:49 Sebastian Andrzej Siewior
  2014-07-09 17:49 ` [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port Sebastian Andrzej Siewior
                   ` (6 more replies)
  0 siblings, 7 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: linux-arm-kernel, Tony Lindgren, Felipe Balbi, linux-kernel,
	linux-serial

This is version three of the patch set. Unless something serious comes up
I would drop the RFC on the next post.

So far I should have everything covered up comparing to the omap-serial
driver except for the throttle callbacks. And now I would slowly start
looking into DMA support…

Sebastian

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

* [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
@ 2014-07-09 17:49 ` Sebastian Andrzej Siewior
  2014-07-10 14:30   ` Olivier Galibert
  2014-07-09 17:49 ` [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup() Sebastian Andrzej Siewior
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: Tony Lindgren, Sebastian Andrzej Siewior, linux-kernel,
	Felipe Balbi, linux-serial, linux-arm-kernel

There is no access to access a struct uart_8250_port for a specific
line. This is only required outside of the 8250/uart callbacks like for
devices' suspend & remove callbacks. For those the 8250-core provides
wrapper like serial8250_unregister_port() which passes the struct
to the proper function based on the line argument.

For runtime suspend I need access to this struct not only to make
serial_out() work but also to properly restore up->ier and up->mcr.

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

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 1ebf853..34c3cd1 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -110,6 +110,8 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
 	up->dl_write(up, value);
 }
 
+struct uart_8250_port *serial8250_get_port(int line);
+
 #if defined(__alpha__) && !defined(CONFIG_PCI)
 /*
  * Digital did something really horribly wrong with the OUT1 and OUT2
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 7a91c6d..6db2ee2 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -2755,6 +2755,23 @@ static struct uart_ops serial8250_pops = {
 
 static struct uart_8250_port serial8250_ports[UART_NR];
 
+/**
+ * serial8250_get_port - retrieve struct uart_8250_port
+ * @line: serial line number
+ *
+ * This function retrieves struct uart_8250_port for the specific line.
+ * This struct *must* *not* be used to perform a 8250 or serial core operation
+ * which is not accessible otherwise. Its only purpose is to make the struct
+ * accessible to the runtime-pm callbacks for context suspend/restore.
+ * The lock assumption made here is none because runtime-pm suspend/resume
+ * callbacks should not be invoked there is any operation performed on the port.
+ */
+struct uart_8250_port *serial8250_get_port(int line)
+{
+	return &serial8250_ports[line];
+}
+EXPORT_SYMBOL_GPL(serial8250_get_port);
+
 static void (*serial8250_isa_config)(int port, struct uart_port *up,
 	unsigned short *capabilities);
 
-- 
2.0.1

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

* [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup()
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
  2014-07-09 17:49 ` [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port Sebastian Andrzej Siewior
@ 2014-07-09 17:49 ` Sebastian Andrzej Siewior
  2014-07-10 14:54   ` One Thousand Gnomes
  2014-07-10 14:55   ` Sebastian Andrzej Siewior
  2014-07-09 17:49 ` [PATCH 3/6] tty: serial: 8250 core: add runtime pm Sebastian Andrzej Siewior
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: linux-arm-kernel, Tony Lindgren, Felipe Balbi, linux-kernel,
	linux-serial, Sebastian Andrzej Siewior

The OMAP version of the 8250 can actually use 1:1 serial8250_startup().
However it needs to be extended by a wakeup irq which should to be
requested & enabled at ->startup() time and disabled at ->shutdown() time.

v1…v2: add shutdown callback

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_core.c | 22 ++++++++++++++++++++--
 include/linux/serial_8250.h         |  2 ++
 include/linux/serial_core.h         |  2 ++
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 6db2ee2..d37eb08 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1939,7 +1939,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
 
 #endif /* CONFIG_CONSOLE_POLL */
 
-static int serial8250_startup(struct uart_port *port)
+int serial8250_do_startup(struct uart_port *port)
 {
 	struct uart_8250_port *up =
 		container_of(port, struct uart_8250_port, port);
@@ -2191,8 +2191,17 @@ static int serial8250_startup(struct uart_port *port)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(serial8250_do_startup);
 
-static void serial8250_shutdown(struct uart_port *port)
+static int serial8250_startup(struct uart_port *port)
+{
+	if (port->startup)
+		return port->startup(port);
+	else
+		return serial8250_do_startup(port);
+}
+
+void serial8250_do_shutdown(struct uart_port *port)
 {
 	struct uart_8250_port *up =
 		container_of(port, struct uart_8250_port, port);
@@ -2243,6 +2252,15 @@ static void serial8250_shutdown(struct uart_port *port)
 	if (port->irq)
 		serial_unlink_irq_chain(up);
 }
+EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+	if (port->shutdown)
+		port->shutdown(port);
+	else
+		serial8250_do_shutdown(port);
+}
 
 static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
 {
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index af47a8a..0ec21ec 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -114,6 +114,8 @@ extern void serial8250_early_out(struct uart_port *port, int offset, int value);
 extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
+extern int serial8250_do_startup(struct uart_port *port);
+extern void serial8250_do_shutdown(struct uart_port *port);
 extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
 			     unsigned int oldstate);
 extern int fsl8250_handle_irq(struct uart_port *port);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 5bbb809..6f20ff0 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -122,6 +122,8 @@ struct uart_port {
 	void			(*set_termios)(struct uart_port *,
 				               struct ktermios *new,
 				               struct ktermios *old);
+	int			(*startup)(struct uart_port *port);
+	void			(*shutdown)(struct uart_port *port);
 	int			(*handle_irq)(struct uart_port *);
 	void			(*pm)(struct uart_port *, unsigned int state,
 				      unsigned int old);
-- 
2.0.1

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

* [PATCH 3/6] tty: serial: 8250 core: add runtime pm
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
  2014-07-09 17:49 ` [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port Sebastian Andrzej Siewior
  2014-07-09 17:49 ` [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup() Sebastian Andrzej Siewior
@ 2014-07-09 17:49 ` Sebastian Andrzej Siewior
  2014-07-10  6:28   ` Tony Lindgren
  2014-07-21 13:34   ` Mika Westerberg
  2014-07-09 17:49 ` [PATCH 4/6] tty: serial: 8250-core: reorder serial8250_stop_rx() & serial8250_start_tx() Sebastian Andrzej Siewior
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: linux-arm-kernel, Tony Lindgren, Felipe Balbi, linux-kernel,
	linux-serial, Sebastian Andrzej Siewior, mika.westerberg

While comparing the OMAP-serial and the 8250 part of this I noticed that
the the latter does not use runtime-pm. Here are the pieces. It is
basically a get before first register access and a last_busy + put after
last access.
If I understand this correct, it should do nothing as long as
pm_runtime_use_autosuspend() + pm_runtime_enable() isn't invoked on the
device.

Cc: mika.westerberg@linux.intel.com
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_core.c | 101 +++++++++++++++++++++++++++++++-----
 1 file changed, 88 insertions(+), 13 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index d37eb08..1a91a89 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -38,6 +38,7 @@
 #include <linux/nmi.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #ifdef CONFIG_SPARC
 #include <linux/sunserialcore.h>
 #endif
@@ -553,10 +554,11 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 	 * offset but the UART channel may only write to the corresponding
 	 * bit.
 	 */
+	pm_runtime_get_sync(p->port.dev);
 	if ((p->port.type == PORT_XR17V35X) ||
 	   (p->port.type == PORT_XR17D15X)) {
 		serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
-		return;
+		goto out;
 	}
 
 	if (p->capabilities & UART_CAP_SLEEP) {
@@ -571,7 +573,17 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 			serial_out(p, UART_EFR, 0);
 			serial_out(p, UART_LCR, 0);
 		}
+
+		if (!device_may_wakeup(p->port.dev)) {
+			if (sleep)
+				pm_runtime_forbid(p->port.dev);
+			else
+				pm_runtime_allow(p->port.dev);
+		}
 	}
+out:
+	pm_runtime_mark_last_busy(p->port.dev);
+	pm_runtime_put_autosuspend(p->port.dev);
 }
 
 #ifdef CONFIG_SERIAL_8250_RSA
@@ -1280,6 +1292,7 @@ static void serial8250_stop_tx(struct uart_port *port)
 	struct uart_8250_port *up =
 		container_of(port, struct uart_8250_port, port);
 
+	pm_runtime_get_sync(port->dev);
 	__stop_tx(up);
 
 	/*
@@ -1289,6 +1302,8 @@ static void serial8250_stop_tx(struct uart_port *port)
 		up->acr |= UART_ACR_TXDIS;
 		serial_icr_write(up, UART_ACR, up->acr);
 	}
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 }
 
 static void serial8250_start_tx(struct uart_port *port)
@@ -1296,8 +1311,9 @@ static void serial8250_start_tx(struct uart_port *port)
 	struct uart_8250_port *up =
 		container_of(port, struct uart_8250_port, port);
 
+	pm_runtime_get_sync(port->dev);
 	if (up->dma && !serial8250_tx_dma(up)) {
-		return;
+		goto out;
 	} else if (!(up->ier & UART_IER_THRI)) {
 		up->ier |= UART_IER_THRI;
 		serial_port_out(port, UART_IER, up->ier);
@@ -1318,6 +1334,9 @@ static void serial8250_start_tx(struct uart_port *port)
 		up->acr &= ~UART_ACR_TXDIS;
 		serial_icr_write(up, UART_ACR, up->acr);
 	}
+out:
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 }
 
 static void serial8250_stop_rx(struct uart_port *port)
@@ -1325,9 +1344,14 @@ static void serial8250_stop_rx(struct uart_port *port)
 	struct uart_8250_port *up =
 		container_of(port, struct uart_8250_port, port);
 
+	pm_runtime_get_sync(port->dev);
+
 	up->ier &= ~UART_IER_RLSI;
 	up->port.read_status_mask &= ~UART_LSR_DR;
 	serial_port_out(port, UART_IER, up->ier);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 }
 
 static void serial8250_enable_ms(struct uart_port *port)
@@ -1340,7 +1364,10 @@ static void serial8250_enable_ms(struct uart_port *port)
 		return;
 
 	up->ier |= UART_IER_MSI;
+	pm_runtime_get_sync(port->dev);
 	serial_port_out(port, UART_IER, up->ier);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 }
 
 /*
@@ -1530,9 +1557,17 @@ EXPORT_SYMBOL_GPL(serial8250_handle_irq);
 
 static int serial8250_default_handle_irq(struct uart_port *port)
 {
-	unsigned int iir = serial_port_in(port, UART_IIR);
+	unsigned int iir;
+	int ret;
 
-	return serial8250_handle_irq(port, iir);
+	pm_runtime_get_sync(port->dev);
+
+	iir = serial_port_in(port, UART_IIR);
+	ret = serial8250_handle_irq(port, iir);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+	return ret;
 }
 
 /*
@@ -1790,11 +1825,16 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
 	unsigned long flags;
 	unsigned int lsr;
 
+	pm_runtime_get_sync(port->dev);
+
 	spin_lock_irqsave(&port->lock, flags);
 	lsr = serial_port_in(port, UART_LSR);
 	up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
 	spin_unlock_irqrestore(&port->lock, flags);
 
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+
 	return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
 }
 
@@ -1805,7 +1845,10 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
 	unsigned int status;
 	unsigned int ret;
 
+	pm_runtime_get_sync(port->dev);
 	status = serial8250_modem_status(up);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 
 	ret = 0;
 	if (status & UART_MSR_DCD)
@@ -1838,7 +1881,10 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
 	mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
 
+	pm_runtime_get_sync(port->dev);
 	serial_port_out(port, UART_MCR, mcr);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 }
 
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
@@ -1847,6 +1893,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
 		container_of(port, struct uart_8250_port, port);
 	unsigned long flags;
 
+	pm_runtime_get_sync(port->dev);
 	spin_lock_irqsave(&port->lock, flags);
 	if (break_state == -1)
 		up->lcr |= UART_LCR_SBC;
@@ -1854,6 +1901,8 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
 		up->lcr &= ~UART_LCR_SBC;
 	serial_port_out(port, UART_LCR, up->lcr);
 	spin_unlock_irqrestore(&port->lock, flags);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 }
 
 /*
@@ -1898,12 +1947,23 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
 
 static int serial8250_get_poll_char(struct uart_port *port)
 {
-	unsigned char lsr = serial_port_in(port, UART_LSR);
+	unsigned char lsr;
+	int status;
+
+	pm_runtime_get_sync(port->dev);
 
-	if (!(lsr & UART_LSR_DR))
-		return NO_POLL_CHAR;
+	lsr = serial_port_in(port, UART_LSR);
 
-	return serial_port_in(port, UART_RX);
+	if (!(lsr & UART_LSR_DR)) {
+		status = NO_POLL_CHAR;
+		goto out;
+	}
+
+	status = serial_port_in(port, UART_RX);
+out:
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
+	return status;
 }
 
 
@@ -1914,6 +1974,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
 	struct uart_8250_port *up =
 		container_of(port, struct uart_8250_port, port);
 
+	pm_runtime_get_sync(up->dev);
 	/*
 	 *	First save the IER then disable the interrupts
 	 */
@@ -1935,6 +1996,9 @@ static void serial8250_put_poll_char(struct uart_port *port,
 	 */
 	wait_for_xmitr(up, BOTH_EMPTY);
 	serial_port_out(port, UART_IER, ier);
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
+
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1961,6 +2025,7 @@ int serial8250_do_startup(struct uart_port *port)
 	if (port->iotype != up->cur_iotype)
 		set_io_from_upio(port);
 
+	pm_runtime_get_sync(port->dev);
 	if (port->type == PORT_16C950) {
 		/* Wake up and initialize UART */
 		up->acr = 0;
@@ -1981,7 +2046,6 @@ int serial8250_do_startup(struct uart_port *port)
 	 */
 	enable_rsa(up);
 #endif
-
 	/*
 	 * Clear the FIFO buffers and disable them.
 	 * (they will be reenabled in set_termios())
@@ -2005,7 +2069,8 @@ int serial8250_do_startup(struct uart_port *port)
 	    (serial_port_in(port, UART_LSR) == 0xff)) {
 		printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
 				   serial_index(port));
-		return -ENODEV;
+		retval = -ENODEV;
+		goto out;
 	}
 
 	/*
@@ -2090,7 +2155,7 @@ int serial8250_do_startup(struct uart_port *port)
 	} else {
 		retval = serial_link_irq_chain(up);
 		if (retval)
-			return retval;
+			goto out;
 	}
 
 	/*
@@ -2188,8 +2253,11 @@ int serial8250_do_startup(struct uart_port *port)
 		outb_p(0x80, icp);
 		inb_p(icp);
 	}
-
-	return 0;
+	retval = 0;
+out:
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+	return retval;
 }
 EXPORT_SYMBOL_GPL(serial8250_do_startup);
 
@@ -2207,6 +2275,7 @@ void serial8250_do_shutdown(struct uart_port *port)
 		container_of(port, struct uart_8250_port, port);
 	unsigned long flags;
 
+	pm_runtime_get_sync(port->dev);
 	/*
 	 * Disable interrupts from this port
 	 */
@@ -2246,6 +2315,8 @@ void serial8250_do_shutdown(struct uart_port *port)
 	 * the IRQ chain.
 	 */
 	serial_port_in(port, UART_RX);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
 
 	del_timer_sync(&up->timer);
 	up->timer.function = serial8250_timeout;
@@ -2365,6 +2436,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * Ok, we're now changing the port state.  Do it with
 	 * interrupts disabled.
 	 */
+	pm_runtime_get_sync(port->dev);
 	spin_lock_irqsave(&port->lock, flags);
 
 	/*
@@ -2486,6 +2558,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 	}
 	serial8250_set_mctrl(port, port->mctrl);
 	spin_unlock_irqrestore(&port->lock, flags);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+
 	/* Don't rewrite B0 */
 	if (tty_termios_baud_rate(termios))
 		tty_termios_encode_baud_rate(termios, baud, baud);
-- 
2.0.1

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

* [PATCH 4/6] tty: serial: 8250-core: reorder serial8250_stop_rx() & serial8250_start_tx()
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
                   ` (2 preceding siblings ...)
  2014-07-09 17:49 ` [PATCH 3/6] tty: serial: 8250 core: add runtime pm Sebastian Andrzej Siewior
@ 2014-07-09 17:49 ` Sebastian Andrzej Siewior
  2014-07-09 17:49 ` [PATCH 5/6] tty: serial: 8250-core: add rs485 support Sebastian Andrzej Siewior
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: Tony Lindgren, Sebastian Andrzej Siewior, linux-kernel,
	Felipe Balbi, linux-serial, linux-arm-kernel

With the upcomming rs485 support it is required that
serial8250_stop_rx() is called from serial8250_start_tx(). With this
reordering there is no need for a forward declaration of the former
function.

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

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 1a91a89..c7c3bf7 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1306,6 +1306,21 @@ static void serial8250_stop_tx(struct uart_port *port)
 	pm_runtime_put_autosuspend(port->dev);
 }
 
+static void serial8250_stop_rx(struct uart_port *port)
+{
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+
+	pm_runtime_get_sync(port->dev);
+
+	up->ier &= ~UART_IER_RLSI;
+	up->port.read_status_mask &= ~UART_LSR_DR;
+	serial_port_out(port, UART_IER, up->ier);
+
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+}
+
 static void serial8250_start_tx(struct uart_port *port)
 {
 	struct uart_8250_port *up =
@@ -1339,21 +1354,6 @@ static void serial8250_start_tx(struct uart_port *port)
 	pm_runtime_put_autosuspend(port->dev);
 }
 
-static void serial8250_stop_rx(struct uart_port *port)
-{
-	struct uart_8250_port *up =
-		container_of(port, struct uart_8250_port, port);
-
-	pm_runtime_get_sync(port->dev);
-
-	up->ier &= ~UART_IER_RLSI;
-	up->port.read_status_mask &= ~UART_LSR_DR;
-	serial_port_out(port, UART_IER, up->ier);
-
-	pm_runtime_mark_last_busy(port->dev);
-	pm_runtime_put_autosuspend(port->dev);
-}
-
 static void serial8250_enable_ms(struct uart_port *port)
 {
 	struct uart_8250_port *up =
-- 
2.0.1

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

* [PATCH 5/6] tty: serial: 8250-core: add rs485 support
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
                   ` (3 preceding siblings ...)
  2014-07-09 17:49 ` [PATCH 4/6] tty: serial: 8250-core: reorder serial8250_stop_rx() & serial8250_start_tx() Sebastian Andrzej Siewior
@ 2014-07-09 17:49 ` Sebastian Andrzej Siewior
  2014-07-09 19:01   ` Lennart Sorensen
  2014-07-10 14:52   ` One Thousand Gnomes
  2014-07-09 17:49 ` [PATCH 6/6] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
  2014-07-09 17:58 ` [RFC v3] 8250-core based serial driver for OMAP Sebastian Andrzej Siewior
  6 siblings, 2 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: linux-arm-kernel, Tony Lindgren, Felipe Balbi, linux-kernel,
	linux-serial, Sebastian Andrzej Siewior

So after I stuffed the rs485 support from the omap-serial into
8250-omap, I've been looking at it and the only omap specific part was
the OMAP_UART_SCR_TX_EMPTY part. The driver has always TX_EMPTY set
because the 8250 core expects an interrupt after the TX fifo + shift
register is empty. The rs485 parts seems to wait for half fifo and then
again for the empty fifo. With this change gone it fits fine as generic
code and here it is.

It is expected that the potential rs485 user invokes
serial_omap_probe_rs485() to configure atleast RTS gpio which is a must
have property. The code has been taken from omap-serial driver and
received limited tested due to -ENODEV (the compiler said it works).

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_core.c | 171 ++++++++++++++++++++++++++++++++++++
 include/linux/serial_8250.h         |   6 ++
 2 files changed, 177 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index c7c3bf7..bf06a4c 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -39,6 +39,8 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #ifdef CONFIG_SPARC
 #include <linux/sunserialcore.h>
 #endif
@@ -1281,10 +1283,34 @@ static void autoconfig_irq(struct uart_8250_port *up)
 
 static inline void __stop_tx(struct uart_8250_port *p)
 {
+	if (p->rs485.flags & SER_RS485_ENABLED) {
+		int ret;
+
+		ret = (p->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
+		if (gpio_get_value(p->rts_gpio) != ret) {
+			if (p->rs485.delay_rts_after_send > 0)
+				mdelay(p->rs485.delay_rts_after_send);
+			gpio_set_value(p->rts_gpio, ret);
+		}
+	}
+
 	if (p->ier & UART_IER_THRI) {
 		p->ier &= ~UART_IER_THRI;
 		serial_out(p, UART_IER, p->ier);
 	}
+
+	if ((p->rs485.flags & SER_RS485_ENABLED) &&
+			!(p->rs485.flags & SER_RS485_RX_DURING_TX)) {
+		/*
+		 * Empty the RX FIFO, we are not interested in anything
+		 * received during the half-duplex transmission.
+		 */
+		serial_out(p, UART_FCR, p->fcr | UART_FCR_CLEAR_RCVR);
+		/* Re-enable RX interrupts */
+		p->ier |= UART_IER_RLSI | UART_IER_RDI;
+		p->port.read_status_mask |= UART_LSR_DR;
+		serial_out(p, UART_IER, p->ier);
+	}
 }
 
 static void serial8250_stop_tx(struct uart_port *port)
@@ -1330,6 +1356,20 @@ static void serial8250_start_tx(struct uart_port *port)
 	if (up->dma && !serial8250_tx_dma(up)) {
 		goto out;
 	} else if (!(up->ier & UART_IER_THRI)) {
+
+		if (up->rs485.flags & SER_RS485_ENABLED) {
+			int ret;
+
+			ret = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
+			if (gpio_get_value(up->rts_gpio) != ret) {
+				gpio_set_value(up->rts_gpio, ret);
+				if (up->rs485.delay_rts_before_send > 0)
+					mdelay(up->rs485.delay_rts_before_send);
+			}
+			if (!(up->rs485.flags & SER_RS485_RX_DURING_TX))
+				serial8250_stop_rx(port);
+		}
+
 		up->ier |= UART_IER_THRI;
 		serial_port_out(port, UART_IER, up->ier);
 
@@ -2556,6 +2596,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 			serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
 		serial_port_out(port, UART_FCR, fcr);		/* set fcr */
 	}
+	up->fcr = fcr;
 	serial8250_set_mctrl(port, port->mctrl);
 	spin_unlock_irqrestore(&port->lock, flags);
 	pm_runtime_mark_last_busy(port->dev);
@@ -2811,6 +2852,124 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
 	return 0;
 }
 
+int serial8250_probe_rs485(struct uart_8250_port *up,
+		struct device *dev)
+{
+	struct serial_rs485 *rs485conf = &up->rs485;
+	struct device_node *np = dev->of_node;
+	u32 rs485_delay[2];
+	enum of_gpio_flags flags;
+	int ret;
+
+	rs485conf->flags = 0;
+	if (!np)
+		return 0;
+
+	/* check for tx enable gpio */
+	up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);
+	if (up->rts_gpio == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (!gpio_is_valid(up->rts_gpio))
+		return 0;
+
+	ret = devm_gpio_request(dev, up->rts_gpio, "serial_rts");
+	if (ret < 0)
+		return ret;
+	ret = gpio_direction_output(up->rts_gpio,
+			flags & SER_RS485_RTS_AFTER_SEND);
+	if (ret < 0)
+		return ret;
+
+	up->rts_gpio_valid = true;
+
+	if (of_property_read_bool(np, "rs485-rts-active-high"))
+		rs485conf->flags |= SER_RS485_RTS_ON_SEND;
+	else
+		rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
+
+	if (of_property_read_u32_array(np, "rs485-rts-delay",
+				rs485_delay, 2) == 0) {
+		rs485conf->delay_rts_before_send = rs485_delay[0];
+		rs485conf->delay_rts_after_send = rs485_delay[1];
+	}
+
+	if (of_property_read_bool(np, "rs485-rx-during-tx"))
+		rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+	if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time"))
+		rs485conf->flags |= SER_RS485_ENABLED;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(serial8250_probe_rs485);
+
+static void serial8250_config_rs485(struct uart_port *port,
+		struct serial_rs485 *rs485conf)
+{
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
+	unsigned long flags;
+	unsigned int mode;
+	int val;
+
+	pm_runtime_get_sync(port->dev);
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	/* Disable interrupts from this port */
+	mode = up->ier;
+	up->ier = 0;
+	serial_out(up, UART_IER, 0);
+
+	/* store new config */
+	up->rs485 = *rs485conf;
+
+	/* enable / disable rts */
+	val = (up->rs485.flags & SER_RS485_ENABLED) ?
+		SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
+	val = (up->rs485.flags & val) ? 1 : 0;
+	gpio_set_value(up->rts_gpio, val);
+
+	/* Enable interrupts */
+	up->ier = mode;
+	serial_out(up, UART_IER, up->ier);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+}
+
+static int serial8250_ioctl(struct uart_port *port, unsigned int cmd,
+		unsigned long arg)
+{
+	struct serial_rs485 rs485conf;
+	struct uart_8250_port *up;
+
+	up = container_of(port, struct uart_8250_port, port);
+	switch (cmd) {
+	case TIOCSRS485:
+		if (!gpio_is_valid(up->rts_gpio))
+			return -ENODEV;
+		if (copy_from_user(&rs485conf, (void __user *) arg,
+					sizeof(rs485conf)))
+			return -EFAULT;
+
+		serial8250_config_rs485(port, &rs485conf);
+		break;
+
+	case TIOCGRS485:
+		if (!gpio_is_valid(up->rts_gpio))
+			return -ENODEV;
+		if (copy_to_user((void __user *) arg, &up->rs485,
+					sizeof(rs485conf)))
+			return -EFAULT;
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
 static const char *
 serial8250_type(struct uart_port *port)
 {
@@ -2840,6 +2999,7 @@ static struct uart_ops serial8250_pops = {
 	.request_port	= serial8250_request_port,
 	.config_port	= serial8250_config_port,
 	.verify_port	= serial8250_verify_port,
+	.ioctl		= serial8250_ioctl,
 #ifdef CONFIG_CONSOLE_POLL
 	.poll_get_char = serial8250_get_poll_char,
 	.poll_put_char = serial8250_put_poll_char,
@@ -3375,6 +3535,17 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 		uart->tx_loadsz		= up->tx_loadsz;
 		uart->capabilities	= up->capabilities;
 
+		/*
+		 * gpio_is_valid() is nice but if this struct wasn't initialized
+		 * then it is 0 which is considered as valid. With the ioctl()
+		 * which can enable the rs485 routine we could abuse a gpio.
+		 */
+		if (up->rts_gpio_valid) {
+			uart->rs485		= up->rs485;
+			uart->rts_gpio		= up->rts_gpio;
+		} else
+			uart->rts_gpio = -EINVAL;
+
 		/* Take tx_loadsz from fifosize if it wasn't set separately */
 		if (uart->port.fifosize && !uart->tx_loadsz)
 			uart->tx_loadsz = uart->port.fifosize;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 0ec21ec..056a73f 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -78,6 +78,7 @@ struct uart_8250_port {
 	unsigned char		acr;
 	unsigned char		ier;
 	unsigned char		lcr;
+	unsigned char		fcr;
 	unsigned char		mcr;
 	unsigned char		mcr_mask;	/* mask of user bits */
 	unsigned char		mcr_force;	/* mask of forced bits */
@@ -94,6 +95,9 @@ struct uart_8250_port {
 	unsigned char		msr_saved_flags;
 
 	struct uart_8250_dma	*dma;
+	struct serial_rs485	rs485;
+	int			rts_gpio;
+	bool			rts_gpio_valid;
 
 	/* 8250 specific callbacks */
 	int			(*dl_read)(struct uart_8250_port *);
@@ -107,6 +111,8 @@ void serial8250_resume_port(int line);
 
 extern int early_serial_setup(struct uart_port *port);
 
+extern int serial8250_probe_rs485(struct uart_8250_port *up,
+		struct device *dev);
 extern int serial8250_find_port(struct uart_port *p);
 extern int serial8250_find_port_for_earlycon(void);
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
-- 
2.0.1

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

* [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
                   ` (4 preceding siblings ...)
  2014-07-09 17:49 ` [PATCH 5/6] tty: serial: 8250-core: add rs485 support Sebastian Andrzej Siewior
@ 2014-07-09 17:49 ` Sebastian Andrzej Siewior
  2014-07-10  7:09   ` Tony Lindgren
  2014-08-08 11:05   ` Heikki Krogerus
  2014-07-09 17:58 ` [RFC v3] 8250-core based serial driver for OMAP Sebastian Andrzej Siewior
  6 siblings, 2 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:49 UTC (permalink / raw)
  To: linux-omap
  Cc: linux-arm-kernel, Tony Lindgren, Felipe Balbi, linux-kernel,
	linux-serial, Sebastian Andrzej Siewior

This patch provides a 8250-core based UART driver for the internal OMAP
UART. The longterm goal is to provide the same functionality as the
current OMAP uart driver and hopefully DMA support which could borrowed
from the 8250-core.

It has been only tested as console UART on am335x-evm and dra7-evm.
The device name is ttyS based instead of ttyO. If a ttyO based node name
is required please ask udev for it.

Missing:
- throttle callback

v2…v3:
	- wire up startup & shutdown for wakeup-irq handling.
	- RS485 handling (well the core does).

v1…v2:
	- added runtime PM. Could somebody could plese double check
	  this? I seems to be enabled and nothing explodes. However
	  serial_omap_get_context_loss_count() & enable_wakeup() are
	  NULL pointer (in the omap-serial driver). So I am not sure how
	  this supposed to work :)
	- added omap_8250_set_termios()

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/tty/serial/8250/8250_core.c |   8 +
 drivers/tty/serial/8250/8250_omap.c | 881 ++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig     |   9 +
 drivers/tty/serial/8250/Makefile    |   1 +
 include/uapi/linux/serial_core.h    |   3 +-
 5 files changed, 901 insertions(+), 1 deletion(-)
 create mode 100644 drivers/tty/serial/8250/8250_omap.c

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index bf06a4c..1cbfc8c 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -263,6 +263,12 @@ static const struct serial8250_config uart_config[] = {
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
 		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
 	},
+	[PORT_OMAP_16750] = {
+		.name		= "OMAP",
+		.fifo_size	= 64,
+		.tx_loadsz	= 64,
+		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+	},
 	[PORT_TEGRA] = {
 		.name		= "Tegra",
 		.fifo_size	= 32,
@@ -1340,6 +1346,8 @@ static void serial8250_stop_rx(struct uart_port *port)
 	pm_runtime_get_sync(port->dev);
 
 	up->ier &= ~UART_IER_RLSI;
+	if (port->type == PORT_OMAP_16750)
+		up->ier &= ~UART_IER_RDI;
 	up->port.read_status_mask &= ~UART_LSR_DR;
 	serial_port_out(port, UART_IER, up->ier);
 
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
new file mode 100644
index 0000000..b7fdbf6
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -0,0 +1,881 @@
+/*
+ * 8250-core based driver for the OMAP internal UART
+ *
+ *  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 UART_DLL_EM 9
+#define UART_DLM_EM 10
+
+#define DEFAULT_CLK_SPEED	48000000 /* 48 Mhz*/
+
+#define UART_ERRATA_i202_MDR1_ACCESS	(1 << 0)
+#define OMAP_UART_WER_HAS_TX_WAKEUP	(1 << 1)
+
+/* 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)
+
+/* 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
+
+/* 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_SW_CLR	0xf0
+#define OMAP_UART_TCR_TRIG	0x0f
+
+#define OMAP_UART_WER_MOD_WKUP	0x7f
+#define OMAP_UART_TX_WAKEUP_EN	(1 << 7)
+
+#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 serial8250_omap_priv {
+	int line;
+	u32 habit;
+	u32 fcr;
+	u32 mdr1;
+	u32 efr;
+	u32 quot;
+	u32 scr;
+	u32 wer;
+
+	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;
+};
+
+static u32 uart_read(struct uart_8250_port *up, u32 reg)
+{
+	return readl(up->port.membase + (reg << up->port.regshift));
+}
+
+static void uart_write(struct uart_8250_port *up, u32 reg, u32 val)
+{
+	writel(val, 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, u8 mdr1)
+{
+	struct serial8250_omap_priv *priv = up->port.private_data;
+	u8 timeout = 255;
+
+	serial_out(up, UART_OMAP_MDR1, mdr1);
+	udelay(2);
+	serial_out(up, UART_FCR, priv->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 serial8250_omap_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);
+
+	abs_d13 = abs(baud - port->uartclk / 13 / div_13);
+	abs_d16 = abs(baud - port->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;
+	}
+}
+
+/*
+ * 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 serial8250_omap_priv *priv = up->port.private_data;
+	unsigned char cval = 0;
+	unsigned long flags = 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_irqsave(&port->lock, flags);
+
+	/*
+	 * 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 & (BRKINT | 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;
+	serial_out(up, UART_IER, up->ier);
+
+	serial_out(up, UART_LCR, cval);         /* reset DLAB */
+	up->lcr = cval;
+
+	/* Up to here it was mostly serial8250_do_set_termios() */
+
+	/* FCR can be changed only when the
+	 * baud clock is not running
+	 * DLL_REG and DLH_REG set to 0.
+	 */
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_DLL, 0);
+	serial_out(up, UART_DLM, 0);
+	serial_out(up, UART_LCR, 0);
+
+	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, up->mcr | UART_MCR_TCRTLR);
+
+	priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY;
+	/*
+	 * NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK sets Enables the
+	 * granularity of 1 for TRIGGER RX level. Along with setting RX FIFO
+	 * trigger level to 1 (as noted below, 16 characters) and TLR[3:0] to
+	 * zero this will result RX FIFO threshold level to 1 character.
+	 * Transmit FIFO threshold is set to 32 spaces. With SCR_TX_EMPTY set,
+	 * we receive an interrupt once TX FIFO (and shift) is empty as this is
+	 * what The irq routine currently expects to happen.
+	 */
+	priv->fcr = UART_FCR6_R_TRIGGER_16 | UART_FCR6_T_TRIGGER_24 |
+		UART_FCR_ENABLE_FIFO;
+
+	serial_out(up, UART_FCR, priv->fcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	serial_out(up, UART_OMAP_SCR, priv->scr);
+
+	/* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, 0);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+
+	/* Protocol, Baud Rate, and Interrupt Settings */
+
+	if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_8250_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
+	else
+		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, UART_EFR_ECB);
+
+	serial_out(up, UART_LCR, 0);
+	serial_out(up, UART_IER, 0);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	serial_dl_write(up, priv->quot);
+
+	serial_out(up, UART_LCR, 0);
+	serial_out(up, UART_IER, up->ier);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	serial_out(up, UART_EFR, 0);
+	serial_out(up, UART_LCR, up->lcr);
+
+	if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_8250_mdr1_errataset(up, priv->mdr1);
+	else
+		serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+
+	/* Configure flow control */
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	/* XON1/XOFF1 accessible mode B, TCRTLR=0, ECB=0 */
+	serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+	serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+	/* Enable access to TCR/TLR */
+	serial_out(up, UART_EFR, UART_EFR_ECB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+
+	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+
+	priv->efr = 0;
+	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;
+	}
+
+	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;
+		else
+			up->mcr &= ~UART_MCR_XONANY;
+	}
+	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, 0);
+	serial_out(up, UART_LCR, up->lcr);
+
+	port->ops->set_mctrl(port, port->mctrl);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	pm_runtime_mark_last_busy(port->dev);
+	pm_runtime_put_autosuspend(port->dev);
+
+	/* calculate wakeup latency constraint */
+	priv->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8);
+	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 serial8250_omap_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);
+
+	if (!device_may_wakeup(port->dev)) {
+		if (!state)
+			pm_runtime_forbid(port->dev);
+		else
+			pm_runtime_allow(port->dev);
+	}
+
+	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 serial8250_omap_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 serial_omap_uart_qos_work(struct work_struct *work)
+{
+	struct serial8250_omap_priv *priv;
+
+	priv = container_of(work, struct serial8250_omap_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 serial8250_omap_priv *priv = port->private_data;
+
+	int ret;
+
+	if (priv->wakeirq) {
+		ret = request_irq(priv->wakeirq, omap_wake_irq,
+				port->irqflags, "wakeup irq", port);
+		if (ret)
+			return ret;
+		disable_irq(priv->wakeirq);
+	}
+
+	ret = serial8250_do_startup(port);
+	if (ret)
+		goto err;
+
+	/* 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);
+	return 0;
+err:
+	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 serial8250_omap_priv *priv = port->private_data;
+
+	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 int serial8250_omap_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 serial8250_omap_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) {
+		dev_err(&pdev->dev, "unable to allocate private data\n");
+		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 is
+	 * enabled via EFR instead of MCR.
+	 */
+	up.port.type = PORT_OMAP_16750;
+	up.port.iotype = UPIO_MEM32;
+	up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE;
+	up.port.private_data = priv;
+
+	up.port.regshift = 2;
+	up.port.fifosize = 64;
+
+	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;
+	/*
+	 * XXX
+	 * throttle
+	 * 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);
+		ret = serial8250_probe_rs485(&up, &pdev->dev);
+		if (ret)
+			return ret;
+	} 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, serial_omap_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 serial8250_omap_remove(struct platform_device *pdev)
+{
+	struct serial8250_omap_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 serial_omap_enable_wakeirq(struct serial8250_omap_priv *priv,
+		bool enable)
+{
+	if (!priv->wakeirq)
+		return;
+
+	if (enable)
+		enable_irq(priv->wakeirq);
+	else
+		disable_irq_nosync(priv->wakeirq);
+}
+
+static void serial_omap_enable_wakeup(struct serial8250_omap_priv *priv,
+		bool enable)
+{
+	if (enable == priv->wakeups_enabled)
+		return;
+
+	serial_omap_enable_wakeirq(priv, enable);
+	priv->wakeups_enabled = enable;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int serial_omap_prepare(struct device *dev)
+{
+	struct serial8250_omap_priv *priv = dev_get_drvdata(dev);
+
+	pr_err("%s(%d)\n", __func__, __LINE__);
+	if (!priv)
+		return 0;
+	priv->is_suspending = true;
+	return 0;
+}
+
+static void serial_omap_complete(struct device *dev)
+{
+	struct serial8250_omap_priv *priv = dev_get_drvdata(dev);
+
+	pr_err("%s(%d)\n", __func__, __LINE__);
+	if (!priv)
+		return;
+	priv->is_suspending = false;
+}
+
+static int serial_omap_suspend(struct device *dev)
+{
+	struct serial8250_omap_priv *priv = dev_get_drvdata(dev);
+
+	serial8250_suspend_port(priv->line);
+	flush_work(&priv->qos_work);
+
+	if (device_may_wakeup(dev))
+		serial_omap_enable_wakeup(priv, true);
+	else
+		serial_omap_enable_wakeup(priv, false);
+	return 0;
+}
+
+static int serial_omap_resume(struct device *dev)
+{
+	struct serial8250_omap_priv *priv = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		serial_omap_enable_wakeup(priv, false);
+
+	serial8250_resume_port(priv->line);
+	return 0;
+}
+#else
+#define serial_omap_prepare NULL
+#define serial_omap_complete NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int serial_omap_lost_context(struct serial8250_omap_priv *priv)
+{
+	struct uart_8250_port *up;
+	u32 val;
+
+	up = serial8250_get_port(priv->line);
+	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 serial_omap_runtime_suspend(struct device *dev)
+{
+	struct serial8250_omap_priv *priv = dev_get_drvdata(dev);
+
+	/*
+	 * 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) {
+		struct uart_8250_port *up;
+
+		up = serial8250_get_port(priv->line);
+		if (uart_console(&up->port))
+			return -EBUSY;
+	}
+
+	serial_omap_enable_wakeup(priv, true);
+
+	priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+	schedule_work(&priv->qos_work);
+	return 0;
+}
+
+static void serial_omap_restore_context(struct serial8250_omap_priv *priv)
+{
+	struct uart_8250_port *up;
+
+	up = serial8250_get_port(priv->line);
+
+	if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_8250_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
+	else
+		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+	serial_out(up, UART_EFR, UART_EFR_ECB);
+	serial_out(up, UART_LCR, 0x0); /* Operational mode */
+	serial_out(up, UART_IER, 0x0);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+
+	serial_dl_write(up, priv->quot);
+
+	serial_out(up, UART_LCR, 0x0); /* Operational mode */
+	serial_out(up, UART_IER, up->ier);
+	serial_out(up, UART_FCR, priv->fcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+	serial_out(up, UART_OMAP_SCR, priv->scr);
+	serial_out(up, UART_EFR, priv->efr);
+	serial_out(up, UART_LCR, up->lcr);
+	if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+		omap_8250_mdr1_errataset(up, priv->mdr1);
+	else
+		serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+	serial_out(up, UART_OMAP_WER, priv->wer);
+}
+
+static int serial_omap_runtime_resume(struct device *dev)
+{
+	struct serial8250_omap_priv *priv = dev_get_drvdata(dev);
+	int loss_cntx;
+
+	/* In case runtime-pm tries this before we are setup */
+	if (!priv)
+		return 0;
+	serial_omap_enable_wakeup(priv, false);
+	loss_cntx = serial_omap_lost_context(priv);
+
+	if (loss_cntx)
+		serial_omap_restore_context(priv);
+
+	priv->latency = priv->calc_latency;
+	schedule_work(&priv->qos_work);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops serial8250_omap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume)
+	SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend,
+			serial_omap_runtime_resume, NULL)
+	.prepare        = serial_omap_prepare,
+	.complete       = serial_omap_complete,
+};
+
+static const struct of_device_id serial8250_omap_dt_ids[] = {
+	{ .compatible = "ti,omap2-uart" },
+	{ .compatible = "ti,omap3-uart" },
+	{ .compatible = "ti,omap4-uart" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, serial8250_omap_dt_ids);
+
+static struct platform_driver serial8250_omap_platform_driver = {
+	.driver = {
+		.name		= "serial8250-omap",
+		.pm		= &serial8250_omap_dev_pm_ops,
+		.of_match_table = serial8250_omap_dt_ids,
+		.owner		= THIS_MODULE,
+	},
+	.probe			= serial8250_omap_probe,
+	.remove			= serial8250_omap_remove,
+};
+module_platform_driver(serial8250_omap_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 349ee59..7a5073b 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -298,3 +298,12 @@ config SERIAL_8250_RT288X
 	  If you have a Ralink RT288x/RT305x SoC based board and want to use the
 	  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 is in early stage and uses ttyS instead of ttyO.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 36d68d0..4bac392 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -20,3 +20,4 @@ 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
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 5820269..74f9b11 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -54,7 +54,8 @@
 #define PORT_ALTR_16550_F32 26	/* Altera 16550 UART with 32 FIFOs */
 #define PORT_ALTR_16550_F64 27	/* Altera 16550 UART with 64 FIFOs */
 #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
-#define PORT_MAX_8250	28	/* max port ID */
+#define PORT_OMAP_16750	29	/* TI's OMAP internal 16C750 compatible UART */
+#define PORT_MAX_8250	29	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
-- 
2.0.1

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

* [RFC v3] 8250-core based serial driver for OMAP
  2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
                   ` (5 preceding siblings ...)
  2014-07-09 17:49 ` [PATCH 6/6] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
@ 2014-07-09 17:58 ` Sebastian Andrzej Siewior
  6 siblings, 0 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-09 17:58 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, Tony Lindgren, linux-serial, Felipe Balbi,
	linux-arm-kernel, linux-kernel

+Subject
On 2014-07-09 19:49:31 [+0200], Sebastian Andrzej Siewior wrote:
> This is version three of the patch set. Unless something serious comes up
> I would drop the RFC on the next post.
> 
> So far I should have everything covered up comparing to the omap-serial
> driver except for the throttle callbacks. And now I would slowly start
> looking into DMA support…
> 
Sebastian

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

* Re: [PATCH 5/6] tty: serial: 8250-core: add rs485 support
  2014-07-09 17:49 ` [PATCH 5/6] tty: serial: 8250-core: add rs485 support Sebastian Andrzej Siewior
@ 2014-07-09 19:01   ` Lennart Sorensen
  2014-07-10 15:55     ` Sebastian Andrzej Siewior
  2014-07-10 14:52   ` One Thousand Gnomes
  1 sibling, 1 reply; 76+ messages in thread
From: Lennart Sorensen @ 2014-07-09 19:01 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	linux-kernel, linux-serial

On Wed, Jul 09, 2014 at 07:49:36PM +0200, Sebastian Andrzej Siewior wrote:
> So after I stuffed the rs485 support from the omap-serial into
> 8250-omap, I've been looking at it and the only omap specific part was
> the OMAP_UART_SCR_TX_EMPTY part. The driver has always TX_EMPTY set
> because the 8250 core expects an interrupt after the TX fifo + shift
> register is empty. The rs485 parts seems to wait for half fifo and then
> again for the empty fifo. With this change gone it fits fine as generic
> code and here it is.
> 
> It is expected that the potential rs485 user invokes
> serial_omap_probe_rs485() to configure atleast RTS gpio which is a must
> have property. The code has been taken from omap-serial driver and
> received limited tested due to -ENODEV (the compiler said it works).
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  drivers/tty/serial/8250/8250_core.c | 171 ++++++++++++++++++++++++++++++++++++
>  include/linux/serial_8250.h         |   6 ++
>  2 files changed, 177 insertions(+)
> 
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index c7c3bf7..bf06a4c 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -39,6 +39,8 @@
>  #include <linux/mutex.h>
>  #include <linux/slab.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
>  #ifdef CONFIG_SPARC
>  #include <linux/sunserialcore.h>
>  #endif
> @@ -1281,10 +1283,34 @@ static void autoconfig_irq(struct uart_8250_port *up)
>  
>  static inline void __stop_tx(struct uart_8250_port *p)
>  {
> +	if (p->rs485.flags & SER_RS485_ENABLED) {
> +		int ret;
> +
> +		ret = (p->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
> +		if (gpio_get_value(p->rts_gpio) != ret) {
> +			if (p->rs485.delay_rts_after_send > 0)
> +				mdelay(p->rs485.delay_rts_after_send);
> +			gpio_set_value(p->rts_gpio, ret);

Usually the delay for RS485 is done in bit times, not msec.  Not sure
how you expect this to work.  Not sure doing it in software is precise
enough either.  It probably should be calculated based on the current
baudrate with a bit time rather than msec in the DT data.  No one wants
to have to change the DT data to change the baud rate.  After all this
is very often used with modbus and the modbus rules specify turn around
times in bit times.

I hope TI puts this into the UART in future designs where it belongs
(similar to what Exar and many others already did).

-- 
Len Sorensen

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

* Re: [PATCH 3/6] tty: serial: 8250 core: add runtime pm
  2014-07-09 17:49 ` [PATCH 3/6] tty: serial: 8250 core: add runtime pm Sebastian Andrzej Siewior
@ 2014-07-10  6:28   ` Tony Lindgren
  2014-07-16  8:26     ` Sebastian Andrzej Siewior
  2014-07-21 13:34   ` Mika Westerberg
  1 sibling, 1 reply; 76+ messages in thread
From: Tony Lindgren @ 2014-07-10  6:28 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel,
	linux-serial, mika.westerberg

* Sebastian Andrzej Siewior <bigeasy@linutronix.de> [140709 10:52]:
> While comparing the OMAP-serial and the 8250 part of this I noticed that
> the the latter does not use runtime-pm. Here are the pieces. It is
> basically a get before first register access and a last_busy + put after
> last access.
> If I understand this correct, it should do nothing as long as
> pm_runtime_use_autosuspend() + pm_runtime_enable() isn't invoked on the
> device.
...

> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -571,7 +573,17 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
>  			serial_out(p, UART_EFR, 0);
>  			serial_out(p, UART_LCR, 0);
>  		}
> +
> +		if (!device_may_wakeup(p->port.dev)) {
> +			if (sleep)
> +				pm_runtime_forbid(p->port.dev);
> +			else
> +				pm_runtime_allow(p->port.dev);
> +		}
>  	}
> +out:
> +	pm_runtime_mark_last_busy(p->port.dev);
> +	pm_runtime_put_autosuspend(p->port.dev);
>  }

The device_may_wakeup logic here is wrong as I described in the
earlier thread. For runtime PM, the wake-up events should be
always enabled. So the device_may_wakeup checks should be only
done for suspend and resume.

Regards,

Tony

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-09 17:49 ` [PATCH 6/6] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
@ 2014-07-10  7:09   ` Tony Lindgren
  2014-07-10 15:47     ` Sebastian Andrzej Siewior
  2014-08-08 11:05   ` Heikki Krogerus
  1 sibling, 1 reply; 76+ messages in thread
From: Tony Lindgren @ 2014-07-10  7:09 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel, linux-serial

* Sebastian Andrzej Siewior <bigeasy@linutronix.de> [140709 10:52]:
> 
> v1…v2:
> 	- added runtime PM. Could somebody could plese double check
> 	  this? I seems to be enabled and nothing explodes. However
> 	  serial_omap_get_context_loss_count() & enable_wakeup() are
> 	  NULL pointer (in the omap-serial driver). So I am not sure how
> 	  this supposed to work :)
> 	- added omap_8250_set_termios()

You can test this pretty easily on beagleboard xm for example
using v3.16-r4:

1. Compile the kernel using omap2plus_defconfig and enable your
   driver. USB EHCI needs to be disabled and OTG port should
   not have a USB cable connected.

2. Boot with init=/bin/sh to keep user space timers to minimum
   at least until you have verified to hit off-idle

3. Enable UART timeouts with something like this. You may need
   to update it for ttyS, I just changed ttyO to ttyS here:

   #!/bin/bash
   uarts=$(find /sys/class/tty/ttyS*/device/power/ -type d)
   for uart in $uarts; do
   	echo 3000 > $uart/autosuspend_delay_ms
   done

   uarts=$(find /sys/class/tty/ttyS*/power/ -type d)
   for uart in $uarts; do
   	echo enabled > $uart/wakeup
   	echo auto > $uart/control
   done

   echo 1 > /sys/kernel/debug/pm_debug/enable_off_mode

4. Wait for UART to time out and verify you hit off-idle by
   looking at the debugfs entry:

   # cat /sys/kernel/debug/pm_debug/count
   ...
   core_pwrdm (ON),OFF:6,RET:0,INA:0,ON:7,RET-LOGIC-OFF:0,RET-MEMBANK1-OFF:0,RET-MEMBANK2-OFF:0
   ...
 
I just tried testing this, but did not get far on my omap3 evm:

[    5.445953] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfb020000
[    5.453674] Internal error: : 1028 [#1] SMP ARM
[    5.458221] Modules linked in:
[    5.461334] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.16.0-rc4-00006-gaab2c6a #98
[    5.469024] task: ce058b00 ti: ce05a000 task.ti: ce05a000
[    5.474456] PC is at mem32_serial_in+0xc/0x1c
[    5.478851] LR is at serial8250_do_startup+0xc8/0x89c
[    5.483917] pc : [<c0346f90>]    lr : [<c034ab2c>]    psr: 60000113
[    5.483917] sp : ce05bd10  ip : c0a0aba8  fp : ce275400
[    5.495452] r10: 00000000  r9 : cda7a680  r8 : ce27568c
[    5.500701] r7 : ce275400  r6 : 00000000  r5 : ce280408  r4 : c10b6234
[    5.507263] r3 : fb020000  r2 : 00000002  r1 : fb020000  r0 : c10b6234
[    5.513854] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
[    5.521179] Control: 10c5387d  Table: 80004019  DAC: 00000015
[    5.526977] Process swapper/0 (pid: 1, stack limit = 0xce05a248)
[    5.532989] Stack: (0xce05bd10 to 0xce05c000)
...
[    5.734771] [<c0346f90>] (mem32_serial_in) from [<c034ab2c>] (serial8250_do_startup+0xc8/0x89c)
[    5.743530] [<c034ab2c>] (serial8250_do_startup) from [<c03461f8>] (uart_startup.part.3+0x7c/0x1dc)
[    5.752624] [<c03461f8>] (uart_startup.part.3) from [<c0346d68>] (uart_open+0xe4/0x124)
[    5.760681] [<c0346d68>] (uart_open) from [<c032c19c>] (tty_open+0x130/0x58c)
[    5.767852] [<c032c19c>] (tty_open) from [<c01216f4>] (chrdev_open+0x9c/0x174)
[    5.775115] [<c01216f4>] (chrdev_open) from [<c011b8d4>] (do_dentry_open+0x1d0/0x310)
[    5.783020] [<c011b8d4>] (do_dentry_open) from [<c011bd98>] (finish_open+0x34/0x4c)
[    5.790710] [<c011bd98>] (finish_open) from [<c012a8f8>] (do_last.isra.27+0x5a4/0xb98)
[    5.798675] [<c012a8f8>] (do_last.isra.27) from [<c012afa0>] (path_openat+0xb4/0x5e4)
[    5.806549] [<c012afa0>] (path_openat) from [<c012b7dc>] (do_filp_open+0x2c/0x80)
[    5.814086] [<c012b7dc>] (do_filp_open) from [<c011cd14>] (do_sys_open+0x100/0x1d0)
[    5.821777] [<c011cd14>] (do_sys_open) from [<c07b7ce0>] (kernel_init_freeable+0x124/0x1c8)
[    5.830200] [<c07b7ce0>] (kernel_init_freeable) from [<c054eb90>] (kernel_init+0x8/0xe4)
[    5.838348] [<c054eb90>] (kernel_init) from [<c000e868>] (ret_from_fork+0x14/0x2c)

Sounds like the clocks are not enabled properly?

Regards,

Tony

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

* Re: [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port
  2014-07-09 17:49 ` [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port Sebastian Andrzej Siewior
@ 2014-07-10 14:30   ` Olivier Galibert
  2014-07-16  8:22     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 76+ messages in thread
From: Olivier Galibert @ 2014-07-10 14:30 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Tony Lindgren, Linux Kernel Mailing List, Felipe Balbi,
	linux-serial, linux-omap, linux-arm-kernel

On Wed, Jul 9, 2014 at 7:49 PM, Sebastian Andrzej Siewior
<bigeasy@linutronix.de> wrote:
> + * The lock assumption made here is none because runtime-pm suspend/resume
> + * callbacks should not be invoked there is any operation performed on the port.

I think there's a missing "if"?

Best,

  OG.

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

* Re: [PATCH 5/6] tty: serial: 8250-core: add rs485 support
  2014-07-09 17:49 ` [PATCH 5/6] tty: serial: 8250-core: add rs485 support Sebastian Andrzej Siewior
  2014-07-09 19:01   ` Lennart Sorensen
@ 2014-07-10 14:52   ` One Thousand Gnomes
  1 sibling, 0 replies; 76+ messages in thread
From: One Thousand Gnomes @ 2014-07-10 14:52 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	linux-kernel, linux-serial

>  static inline void __stop_tx(struct uart_8250_port *p)
>  {
> +	if (p->rs485.flags & SER_RS485_ENABLED) {
> +		int ret;
> +
> +		ret = (p->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
> +		if (gpio_get_value(p->rts_gpio) != ret) {
> +			if (p->rs485.delay_rts_after_send > 0)
> +				mdelay(p->rs485.delay_rts_after_send);
> +			gpio_set_value(p->rts_gpio, ret);
> +		}

RTS is not normally a GPIO. We should be controlling the UART RTS here,
and if the UART has a magic special case RTS wired to a GPIO then really
the hardware specific part should handle that gunge. I don't care whether
the drive does it via serial_out magic or a more explicit hook but it
doesn't belong here in core code.

Likewise the mdelay probably should be in the device specific bits or
controlled by a flag as not all hardware is so braindead.

> @@ -1330,6 +1356,20 @@ static void serial8250_start_tx(struct uart_port *port)
>  	if (up->dma && !serial8250_tx_dma(up)) {

Ditto

> +int serial8250_probe_rs485(struct uart_8250_port *up,
> +		struct device *dev)
> +{
> +	struct serial_rs485 *rs485conf = &up->rs485;
> +	struct device_node *np = dev->of_node;
> +	u32 rs485_delay[2];
> +	enum of_gpio_flags flags;
> +	int ret;
> +
> +	rs485conf->flags = 0;
> +	if (!np)
> +		return 0;
> +
> +	/* check for tx enable gpio */
> +	up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);

No of_ dependencies in core 8250.c either please. That looks a perfectly
good implementation of serial8250_of_probe_rs485 however, just belongs in
the right place.

> +static int serial8250_ioctl(struct uart_port *port, unsigned int cmd,
> +		unsigned long arg)
> +{
> +	struct serial_rs485 rs485conf;
> +	struct uart_8250_port *up;
> +
> +	up = container_of(port, struct uart_8250_port, port);
> +	switch (cmd) {
> +	case TIOCSRS485:
> +		if (!gpio_is_valid(up->rts_gpio))
> +			return -ENODEV;

GPIO assumption again needs to go


> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index 0ec21ec..056a73f 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -78,6 +78,7 @@ struct uart_8250_port {
>  	unsigned char		acr;
>  	unsigned char		ier;
>  	unsigned char		lcr;
> +	unsigned char		fcr;
>  	unsigned char		mcr;
>  	unsigned char		mcr_mask;	/* mask of user bits */
>  	unsigned char		mcr_force;	/* mask of forced bits */
> @@ -94,6 +95,9 @@ struct uart_8250_port {
>  	unsigned char		msr_saved_flags;
>  
>  	struct uart_8250_dma	*dma;
> +	struct serial_rs485	rs485;
> +	int			rts_gpio;
> +	bool			rts_gpio_valid;

Keeping the gpio here doesn't look unreasonable if one is in use.

Alan

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

* Re: [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup()
  2014-07-09 17:49 ` [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup() Sebastian Andrzej Siewior
@ 2014-07-10 14:54   ` One Thousand Gnomes
  2014-07-10 14:55   ` Sebastian Andrzej Siewior
  1 sibling, 0 replies; 76+ messages in thread
From: One Thousand Gnomes @ 2014-07-10 14:54 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	linux-kernel, linux-serial

On Wed,  9 Jul 2014 19:49:33 +0200
Sebastian Andrzej Siewior <bigeasy@linutronix.de> wrote:

> The OMAP version of the 8250 can actually use 1:1 serial8250_startup().
> However it needs to be extended by a wakeup irq which should to be
> requested & enabled at ->startup() time and disabled at ->shutdown() time.
> 
> v1…v2: add shutdown callback
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

1,2 & 4

Acked by: Alan Cox <alan@linux.intel.com>

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

* Re: [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup()
  2014-07-09 17:49 ` [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup() Sebastian Andrzej Siewior
  2014-07-10 14:54   ` One Thousand Gnomes
@ 2014-07-10 14:55   ` Sebastian Andrzej Siewior
  1 sibling, 0 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-10 14:55 UTC (permalink / raw)
  To: linux-omap
  Cc: linux-arm-kernel, Tony Lindgren, Felipe Balbi, linux-kernel,
	linux-serial

On 07/09/2014 07:49 PM, Sebastian Andrzej Siewior wrote:
> The OMAP version of the 8250 can actually use 1:1 serial8250_startup().
> However it needs to be extended by a wakeup irq which should to be
> requested & enabled at ->startup() time and disabled at ->shutdown() time.
> 
> v1…v2: add shutdown callback

forgot to copy the callbacks in serial8250_register_8250_port().

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-10  7:09   ` Tony Lindgren
@ 2014-07-10 15:47     ` Sebastian Andrzej Siewior
  2014-07-10 16:03       ` Carlos Hernandez
  2014-07-11  6:41       ` Tony Lindgren
  0 siblings, 2 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-10 15:47 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel, linux-serial

On 07/10/2014 09:09 AM, Tony Lindgren wrote:
> You can test this pretty easily on beagleboard xm for example
> using v3.16-r4:

I tried this with am335x-evm, dra7-evm and beaglebone (omap5-uevm and
am335x-evmsk didn't want to boot a kernel and omap4-blaze didn't even
want to show MLO/U-boot) with the same result.

> 1. Compile the kernel using omap2plus_defconfig and enable your
>    driver. USB EHCI needs to be disabled and OTG port should
>    not have a USB cable connected.

EHCI was already disabled in the config. OTG was not connected.

> 2. Boot with init=/bin/sh to keep user space timers to minimum
>    at least until you have verified to hit off-idle

I had network up and configured. Was that okay? I also tried
"ifconfig eth0 down; sleep 10; ifconfig eth0 up" to see if it works.

> 3. Enable UART timeouts with something like this. You may need
>    to update it for ttyS, I just changed ttyO to ttyS here:
> 
>    #!/bin/bash
>    uarts=$(find /sys/class/tty/ttyS*/device/power/ -type d)
>    for uart in $uarts; do
>    	echo 3000 > $uart/autosuspend_delay_ms
>    done
> 
>    uarts=$(find /sys/class/tty/ttyS*/power/ -type d)
>    for uart in $uarts; do
>    	echo enabled > $uart/wakeup
>    	echo auto > $uart/control
>    done
> 
>    echo 1 > /sys/kernel/debug/pm_debug/enable_off_mode
> 
> 4. Wait for UART to time out and verify you hit off-idle by
>    looking at the debugfs entry:
> 
>    # cat /sys/kernel/debug/pm_debug/count
>    ...
>    core_pwrdm (ON),OFF:6,RET:0,INA:0,ON:7,RET-LOGIC-OFF:0,RET-MEMBANK1-OFF:0,RET-MEMBANK2-OFF:0

That core_pwrdm shows only up on dra7. However with both drivers (mine
and the current omap serial) the UART went down after three secs (as
expected) and didn't accept any characters while writing on the
console. If I wrote something on it via network (like echo a >
/dev/ttyO0) it came back and was working as long as I kept it busy. The
thing is that RX does not wake it up. Any idea?
Also, while it was I checked the core_pwrdm and I had ON:1 and OFF:0.
So something is not right.
Since Dra7 has some things missing I tried it on am335x with the same
behavior. Should it work here?

>    ...
>  
> I just tried testing this, but did not get far on my omap3 evm:
> 
> [    5.445953] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfb020000
> [    5.453674] Internal error: : 1028 [#1] SMP ARM
> [    5.458221] Modules linked in:
> [    5.461334] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.16.0-rc4-00006-gaab2c6a #98
> [    5.469024] task: ce058b00 ti: ce05a000 task.ti: ce05a000
> [    5.474456] PC is at mem32_serial_in+0xc/0x1c
> [    5.478851] LR is at serial8250_do_startup+0xc8/0x89c
> [    5.483917] pc : [<c0346f90>]    lr : [<c034ab2c>]    psr: 60000113
> [    5.483917] sp : ce05bd10  ip : c0a0aba8  fp : ce275400
> [    5.495452] r10: 00000000  r9 : cda7a680  r8 : ce27568c
> [    5.500701] r7 : ce275400  r6 : 00000000  r5 : ce280408  r4 : c10b6234
> [    5.507263] r3 : fb020000  r2 : 00000002  r1 : fb020000  r0 : c10b6234
> [    5.513854] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
> [    5.521179] Control: 10c5387d  Table: 80004019  DAC: 00000015
> [    5.526977] Process swapper/0 (pid: 1, stack limit = 0xce05a248)
> [    5.532989] Stack: (0xce05bd10 to 0xce05c000)
> ...
> [    5.734771] [<c0346f90>] (mem32_serial_in) from [<c034ab2c>] (serial8250_do_startup+0xc8/0x89c)
> [    5.743530] [<c034ab2c>] (serial8250_do_startup) from [<c03461f8>] (uart_startup.part.3+0x7c/0x1dc)
> [    5.752624] [<c03461f8>] (uart_startup.part.3) from [<c0346d68>] (uart_open+0xe4/0x124)
> [    5.760681] [<c0346d68>] (uart_open) from [<c032c19c>] (tty_open+0x130/0x58c)
> [    5.767852] [<c032c19c>] (tty_open) from [<c01216f4>] (chrdev_open+0x9c/0x174)
> [    5.775115] [<c01216f4>] (chrdev_open) from [<c011b8d4>] (do_dentry_open+0x1d0/0x310)
> [    5.783020] [<c011b8d4>] (do_dentry_open) from [<c011bd98>] (finish_open+0x34/0x4c)
> [    5.790710] [<c011bd98>] (finish_open) from [<c012a8f8>] (do_last.isra.27+0x5a4/0xb98)
> [    5.798675] [<c012a8f8>] (do_last.isra.27) from [<c012afa0>] (path_openat+0xb4/0x5e4)
> [    5.806549] [<c012afa0>] (path_openat) from [<c012b7dc>] (do_filp_open+0x2c/0x80)
> [    5.814086] [<c012b7dc>] (do_filp_open) from [<c011cd14>] (do_sys_open+0x100/0x1d0)
> [    5.821777] [<c011cd14>] (do_sys_open) from [<c07b7ce0>] (kernel_init_freeable+0x124/0x1c8)
> [    5.830200] [<c07b7ce0>] (kernel_init_freeable) from [<c054eb90>] (kernel_init+0x8/0xe4)
> [    5.838348] [<c054eb90>] (kernel_init) from [<c000e868>] (ret_from_fork+0x14/0x2c)
> 
> Sounds like the clocks are not enabled properly?

puh. So after staring a while at your backtrace I realized that
shutdown & startup callbacks are not overwritten properly. Well, thanks
for that. Anyway, even serial8250_do_startup() has
pm_runtime_get_sync() before first register access so I have no idea
where this is coming from.

> 
> Regards,
> 
> Tony
> 

Sebastian

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

* Re: [PATCH 5/6] tty: serial: 8250-core: add rs485 support
  2014-07-09 19:01   ` Lennart Sorensen
@ 2014-07-10 15:55     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-10 15:55 UTC (permalink / raw)
  To: Lennart Sorensen
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	linux-kernel, linux-serial

On 07/09/2014 09:01 PM, Lennart Sorensen wrote:
>> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
>> index c7c3bf7..bf06a4c 100644
>> --- a/drivers/tty/serial/8250/8250_core.c
>> +++ b/drivers/tty/serial/8250/8250_core.c
>> @@ -1281,10 +1283,34 @@ static void autoconfig_irq(struct uart_8250_port *up)
>>  
>>  static inline void __stop_tx(struct uart_8250_port *p)
>>  {
>> +	if (p->rs485.flags & SER_RS485_ENABLED) {
>> +		int ret;
>> +
>> +		ret = (p->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
>> +		if (gpio_get_value(p->rts_gpio) != ret) {
>> +			if (p->rs485.delay_rts_after_send > 0)
>> +				mdelay(p->rs485.delay_rts_after_send);
>> +			gpio_set_value(p->rts_gpio, ret);
> 
> Usually the delay for RS485 is done in bit times, not msec.  Not sure
> how you expect this to work.  Not sure doing it in software is precise
> enough either.  It probably should be calculated based on the current
> baudrate with a bit time rather than msec in the DT data.  No one wants
> to have to change the DT data to change the baud rate.  After all this
> is very often used with modbus and the modbus rules specify turn around
> times in bit times.

My understanding is that this is not baudrate related. This is the
delay that the hardware (the transceiver) to perform the change and
work.
There is the ioctl() interface which can change the delay, too. The
only required thing is the gpio.

> I hope TI puts this into the UART in future designs where it belongs
> (similar to what Exar and many others already did).
> 

Sebastian

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-10 15:47     ` Sebastian Andrzej Siewior
@ 2014-07-10 16:03       ` Carlos Hernandez
  2014-07-10 16:14         ` menon.nishanth
  2014-07-11  6:41       ` Tony Lindgren
  1 sibling, 1 reply; 76+ messages in thread
From: Carlos Hernandez @ 2014-07-10 16:03 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Tony Lindgren, linux-omap, linux-arm-kernel, Felipe Balbi,
	linux-kernel, linux-serial

On 07/10/2014 11:47 AM, Sebastian Andrzej Siewior wrote:
> That core_pwrdm shows only up on dra7. However with both drivers (mine
> and the current omap serial) the UART went down after three secs (as
> expected) and didn't accept any characters while writing on the
> console. If I wrote something on it via network (like echo a >
> /dev/ttyO0) it came back and was working as long as I kept it busy. The
> thing is that RX does not wake it up. Any idea?

To wakeup from UART you need:
1) Append no_console_suspend to bootargs
2) echo enabled > /sys/devices/ocp.3/4806a000.serial/tty/ttyO0/power/wakeup



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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-10 16:03       ` Carlos Hernandez
@ 2014-07-10 16:14         ` menon.nishanth
  0 siblings, 0 replies; 76+ messages in thread
From: menon.nishanth @ 2014-07-10 16:14 UTC (permalink / raw)
  To: Carlos Hernandez
  Cc: Sebastian Andrzej Siewior, Tony Lindgren, lkml, Felipe Balbi,
	linux-serial, linux-omap, linux-arm-kernel

On Thu, Jul 10, 2014 at 11:03 AM, Carlos Hernandez <ceh@ti.com> wrote:
> 1) Append no_console_suspend to bootargs
Not needed. ideally with pinctrl wakeup capability, this should work.
if you do no_console_suspend, the module is not powered down.

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-10 15:47     ` Sebastian Andrzej Siewior
  2014-07-10 16:03       ` Carlos Hernandez
@ 2014-07-11  6:41       ` Tony Lindgren
  2014-07-16 12:11         ` Sebastian Andrzej Siewior
  1 sibling, 1 reply; 76+ messages in thread
From: Tony Lindgren @ 2014-07-11  6:41 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel, linux-serial

* Sebastian Andrzej Siewior <bigeasy@linutronix.de> [140710 08:50]:
> On 07/10/2014 09:09 AM, Tony Lindgren wrote:
> > You can test this pretty easily on beagleboard xm for example
> > using v3.16-r4:
> 
> I tried this with am335x-evm, dra7-evm and beaglebone (omap5-uevm and
> am335x-evmsk didn't want to boot a kernel and omap4-blaze didn't even
> want to show MLO/U-boot) with the same result.

None of these SoCs support off-idle with mainline kernel so testing
with those is not enough :) Best to use some omap3 based device for
testing this.

So far I have verified that beagleboard xm, n900, and omap3730-evm
all hit off-idle with v3.16-rc4.
 
> > 1. Compile the kernel using omap2plus_defconfig and enable your
> >    driver. USB EHCI needs to be disabled and OTG port should
> >    not have a USB cable connected.
> 
> EHCI was already disabled in the config. OTG was not connected.

OK
 
> > 2. Boot with init=/bin/sh to keep user space timers to minimum
> >    at least until you have verified to hit off-idle
> 
> I had network up and configured. Was that okay? I also tried
> "ifconfig eth0 down; sleep 10; ifconfig eth0 up" to see if it works.

That's fine for GPMC connected devices, devices with Ethernet on
EHCI won't idle properly AFAIK.
 
> > 3. Enable UART timeouts with something like this. You may need
> >    to update it for ttyS, I just changed ttyO to ttyS here:
> > 
> >    #!/bin/bash
> >    uarts=$(find /sys/class/tty/ttyS*/device/power/ -type d)
> >    for uart in $uarts; do
> >    	echo 3000 > $uart/autosuspend_delay_ms
> >    done
> > 
> >    uarts=$(find /sys/class/tty/ttyS*/power/ -type d)
> >    for uart in $uarts; do
> >    	echo enabled > $uart/wakeup
> >    	echo auto > $uart/control
> >    done
> > 
> >    echo 1 > /sys/kernel/debug/pm_debug/enable_off_mode
> > 
> > 4. Wait for UART to time out and verify you hit off-idle by
> >    looking at the debugfs entry:
> > 
> >    # cat /sys/kernel/debug/pm_debug/count
> >    ...
> >    core_pwrdm (ON),OFF:6,RET:0,INA:0,ON:7,RET-LOGIC-OFF:0,RET-MEMBANK1-OFF:0,RET-MEMBANK2-OFF:0
> 
> That core_pwrdm shows only up on dra7. However with both drivers (mine
> and the current omap serial) the UART went down after three secs (as
> expected) and didn't accept any characters while writing on the
> console. If I wrote something on it via network (like echo a >
> /dev/ttyO0) it came back and was working as long as I kept it busy. The
> thing is that RX does not wake it up. Any idea?

If the RX pin does not wake it up, you need to configure the
pinctrl-single entry for it, and configure that pin as a wake-up
interrupt. See the interrupts-extended entry in omap3-beagle-xm.dts.

> Also, while it was I checked the core_pwrdm and I had ON:1 and OFF:0.
> So something is not right.
> Since Dra7 has some things missing I tried it on am335x with the same
> behavior. Should it work here?

Yes only omap3 currently has the pieces needed for off-idle in the
mainline kernel.
 
> > I just tried testing this, but did not get far on my omap3 evm:
> > 
> > [    5.445953] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfb020000
> > [    5.453674] Internal error: : 1028 [#1] SMP ARM
> > [    5.458221] Modules linked in:
> > [    5.461334] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.16.0-rc4-00006-gaab2c6a #98
> > [    5.469024] task: ce058b00 ti: ce05a000 task.ti: ce05a000
> > [    5.474456] PC is at mem32_serial_in+0xc/0x1c
> > [    5.478851] LR is at serial8250_do_startup+0xc8/0x89c
> > [    5.483917] pc : [<c0346f90>]    lr : [<c034ab2c>]    psr: 60000113
> > [    5.483917] sp : ce05bd10  ip : c0a0aba8  fp : ce275400
> > [    5.495452] r10: 00000000  r9 : cda7a680  r8 : ce27568c
> > [    5.500701] r7 : ce275400  r6 : 00000000  r5 : ce280408  r4 : c10b6234
> > [    5.507263] r3 : fb020000  r2 : 00000002  r1 : fb020000  r0 : c10b6234
> > [    5.513854] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
> > [    5.521179] Control: 10c5387d  Table: 80004019  DAC: 00000015
> > [    5.526977] Process swapper/0 (pid: 1, stack limit = 0xce05a248)
> > [    5.532989] Stack: (0xce05bd10 to 0xce05c000)
> > ...
> > [    5.734771] [<c0346f90>] (mem32_serial_in) from [<c034ab2c>] (serial8250_do_startup+0xc8/0x89c)
> > [    5.743530] [<c034ab2c>] (serial8250_do_startup) from [<c03461f8>] (uart_startup.part.3+0x7c/0x1dc)
> > [    5.752624] [<c03461f8>] (uart_startup.part.3) from [<c0346d68>] (uart_open+0xe4/0x124)
> > [    5.760681] [<c0346d68>] (uart_open) from [<c032c19c>] (tty_open+0x130/0x58c)
> > [    5.767852] [<c032c19c>] (tty_open) from [<c01216f4>] (chrdev_open+0x9c/0x174)
> > [    5.775115] [<c01216f4>] (chrdev_open) from [<c011b8d4>] (do_dentry_open+0x1d0/0x310)
> > [    5.783020] [<c011b8d4>] (do_dentry_open) from [<c011bd98>] (finish_open+0x34/0x4c)
> > [    5.790710] [<c011bd98>] (finish_open) from [<c012a8f8>] (do_last.isra.27+0x5a4/0xb98)
> > [    5.798675] [<c012a8f8>] (do_last.isra.27) from [<c012afa0>] (path_openat+0xb4/0x5e4)
> > [    5.806549] [<c012afa0>] (path_openat) from [<c012b7dc>] (do_filp_open+0x2c/0x80)
> > [    5.814086] [<c012b7dc>] (do_filp_open) from [<c011cd14>] (do_sys_open+0x100/0x1d0)
> > [    5.821777] [<c011cd14>] (do_sys_open) from [<c07b7ce0>] (kernel_init_freeable+0x124/0x1c8)
> > [    5.830200] [<c07b7ce0>] (kernel_init_freeable) from [<c054eb90>] (kernel_init+0x8/0xe4)
> > [    5.838348] [<c054eb90>] (kernel_init) from [<c000e868>] (ret_from_fork+0x14/0x2c)
> > 
> > Sounds like the clocks are not enabled properly?
> 
> puh. So after staring a while at your backtrace I realized that
> shutdown & startup callbacks are not overwritten properly. Well, thanks
> for that. Anyway, even serial8250_do_startup() has
> pm_runtime_get_sync() before first register access so I have no idea
> where this is coming from.

Maybe because the console is enabled for that port?

Regards,

Tony

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

* Re: [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port
  2014-07-10 14:30   ` Olivier Galibert
@ 2014-07-16  8:22     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-16  8:22 UTC (permalink / raw)
  To: Olivier Galibert
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	Linux Kernel Mailing List, linux-serial

On 07/10/2014 04:30 PM, Olivier Galibert wrote:
> On Wed, Jul 9, 2014 at 7:49 PM, Sebastian Andrzej Siewior
> <bigeasy@linutronix.de> wrote:
>> + * The lock assumption made here is none because runtime-pm suspend/resume
>> + * callbacks should not be invoked there is any operation performed on the port.
> 
> I think there's a missing "if"?

Thanks, fixed up.

> Best,
> 
>   OG.
> 

Sebastian

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

* Re: [PATCH 3/6] tty: serial: 8250 core: add runtime pm
  2014-07-10  6:28   ` Tony Lindgren
@ 2014-07-16  8:26     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-16  8:26 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel,
	linux-serial, mika.westerberg

On 07/10/2014 08:28 AM, Tony Lindgren wrote:
>> --- a/drivers/tty/serial/8250/8250_core.c
>> +++ b/drivers/tty/serial/8250/8250_core.c
>> @@ -571,7 +573,17 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
>>  			serial_out(p, UART_EFR, 0);
>>  			serial_out(p, UART_LCR, 0);
>>  		}
>> +
>> +		if (!device_may_wakeup(p->port.dev)) {
>> +			if (sleep)
>> +				pm_runtime_forbid(p->port.dev);
>> +			else
>> +				pm_runtime_allow(p->port.dev);
>> +		}
>>  	}
>> +out:
>> +	pm_runtime_mark_last_busy(p->port.dev);
>> +	pm_runtime_put_autosuspend(p->port.dev);
>>  }
> 
> The device_may_wakeup logic here is wrong as I described in the
> earlier thread. For runtime PM, the wake-up events should be
> always enabled. So the device_may_wakeup checks should be only
> done for suspend and resume.

Okay. I dropped it from here.

> 
> Regards,
> 
> Tony
> 

Sebastian

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-11  6:41       ` Tony Lindgren
@ 2014-07-16 12:11         ` Sebastian Andrzej Siewior
  2014-07-16 12:32           ` Tony Lindgren
  0 siblings, 1 reply; 76+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-07-16 12:11 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel, linux-serial

On 07/11/2014 08:41 AM, Tony Lindgren wrote:
>> I tried this with am335x-evm, dra7-evm and beaglebone (omap5-uevm and
>> am335x-evmsk didn't want to boot a kernel and omap4-blaze didn't even
>> want to show MLO/U-boot) with the same result.
> 
> None of these SoCs support off-idle with mainline kernel so testing
> with those is not enough :) Best to use some omap3 based device for
> testing this.
> 
> So far I have verified that beagleboard xm, n900, and omap3730-evm
> all hit off-idle with v3.16-rc4.

Unfortunately I don't have access to any of those devices.

>> I had network up and configured. Was that okay? I also tried
>> "ifconfig eth0 down; sleep 10; ifconfig eth0 up" to see if it works.
> 
> That's fine for GPMC connected devices, devices with Ethernet on
> EHCI won't idle properly AFAIK.

am33xx has proper ethernet (cpsw IP core on SoC and not something
behind USB).

>> That core_pwrdm shows only up on dra7. However with both drivers (mine
>> and the current omap serial) the UART went down after three secs (as
>> expected) and didn't accept any characters while writing on the
>> console. If I wrote something on it via network (like echo a >
>> /dev/ttyO0) it came back and was working as long as I kept it busy. The
>> thing is that RX does not wake it up. Any idea?
> 
> If the RX pin does not wake it up, you need to configure the
> pinctrl-single entry for it, and configure that pin as a wake-up
> interrupt. See the interrupts-extended entry in omap3-beagle-xm.dts.

This does not help. Checking the manual, there is not something like
PIN_OFF_WAKEUPENABLE for am33xx. There is just INPUT/OUTPUT, pull
up/down + enabled/disabled and the mux_mode. For the interrupt, the HW
referenced as omap3_pmx_core touches some bits in the pinmux register
which do not exists on am33xx.

So I have nothing on HW around that could test wakeup scenario.

>> Also, while it was I checked the core_pwrdm and I had ON:1 and OFF:0.
>> So something is not right.
>> Since Dra7 has some things missing I tried it on am335x with the same
>> behavior. Should it work here?
> 
> Yes only omap3 currently has the pieces needed for off-idle in the
> mainline kernel.
>  

Good to know.

>> puh. So after staring a while at your backtrace I realized that
>> shutdown & startup callbacks are not overwritten properly. Well, thanks
>> for that. Anyway, even serial8250_do_startup() has
>> pm_runtime_get_sync() before first register access so I have no idea
>> where this is coming from.
> 
> Maybe because the console is enabled for that port?

Maybe. But I would expect to explode around the console code. Anyway I
fixed it up and prepare next batch.

> 
> Regards,
> 
> Tony


Sebastian

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-16 12:11         ` Sebastian Andrzej Siewior
@ 2014-07-16 12:32           ` Tony Lindgren
  2014-07-16 13:00             ` Sekhar Nori
  0 siblings, 1 reply; 76+ messages in thread
From: Tony Lindgren @ 2014-07-16 12:32 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel, linux-serial

* Sebastian Andrzej Siewior <bigeasy@linutronix.de> [140716 05:14]:
> On 07/11/2014 08:41 AM, Tony Lindgren wrote:
> > 
> > If the RX pin does not wake it up, you need to configure the
> > pinctrl-single entry for it, and configure that pin as a wake-up
> > interrupt. See the interrupts-extended entry in omap3-beagle-xm.dts.
> 
> This does not help. Checking the manual, there is not something like
> PIN_OFF_WAKEUPENABLE for am33xx. There is just INPUT/OUTPUT, pull
> up/down + enabled/disabled and the mux_mode. For the interrupt, the HW
> referenced as omap3_pmx_core touches some bits in the pinmux register
> which do not exists on am33xx.

Right, on am33xx there's no IO chain wake-up path. AFAIK the only way
to provide wake events on am33xx would be to mux the RX pin temporarily
to a GPIO input. And sounds like that may work only if the GPIO is
in the first GPIO bank that's always on. I don't know if the other
GPIO banks on am33xx can provide wake up events.
 
> So I have nothing on HW around that could test wakeup scenario.

Bummer :( I'll give it a try again for the next revision.

Regards,

Tony

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-16 12:32           ` Tony Lindgren
@ 2014-07-16 13:00             ` Sekhar Nori
  0 siblings, 0 replies; 76+ messages in thread
From: Sekhar Nori @ 2014-07-16 13:00 UTC (permalink / raw)
  To: Tony Lindgren, Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Felipe Balbi, linux-kernel, linux-serial

On Wednesday 16 July 2014 06:02 PM, Tony Lindgren wrote:
> * Sebastian Andrzej Siewior <bigeasy@linutronix.de> [140716 05:14]:
>> On 07/11/2014 08:41 AM, Tony Lindgren wrote:
>>>
>>> If the RX pin does not wake it up, you need to configure the
>>> pinctrl-single entry for it, and configure that pin as a wake-up
>>> interrupt. See the interrupts-extended entry in omap3-beagle-xm.dts.
>>
>> This does not help. Checking the manual, there is not something like
>> PIN_OFF_WAKEUPENABLE for am33xx. There is just INPUT/OUTPUT, pull
>> up/down + enabled/disabled and the mux_mode. For the interrupt, the HW
>> referenced as omap3_pmx_core touches some bits in the pinmux register
>> which do not exists on am33xx.
> 
> Right, on am33xx there's no IO chain wake-up path. AFAIK the only way
> to provide wake events on am33xx would be to mux the RX pin temporarily
> to a GPIO input. And sounds like that may work only if the GPIO is
> in the first GPIO bank that's always on. I don't know if the other
> GPIO banks on am33xx can provide wake up events.

No, they cannot.

Thanks,
Sekhar

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

* Re: [PATCH 3/6] tty: serial: 8250 core: add runtime pm
  2014-07-09 17:49 ` [PATCH 3/6] tty: serial: 8250 core: add runtime pm Sebastian Andrzej Siewior
  2014-07-10  6:28   ` Tony Lindgren
@ 2014-07-21 13:34   ` Mika Westerberg
  1 sibling, 0 replies; 76+ messages in thread
From: Mika Westerberg @ 2014-07-21 13:34 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	linux-kernel, linux-serial, Heikki Krogerus

On Wed, Jul 09, 2014 at 07:49:34PM +0200, Sebastian Andrzej Siewior wrote:
> While comparing the OMAP-serial and the 8250 part of this I noticed that
> the the latter does not use runtime-pm. Here are the pieces. It is
> basically a get before first register access and a last_busy + put after
> last access.
> If I understand this correct, it should do nothing as long as
> pm_runtime_use_autosuspend() + pm_runtime_enable() isn't invoked on the
> device.
> 
> Cc: mika.westerberg@linux.intel.com

Sorry for the delay, just came back from vacation.

Adding Heikki, who knows the 8250_dw driver much better than me.
Unfortunately he is still on vacation for next two weeks.

> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  drivers/tty/serial/8250/8250_core.c | 101 +++++++++++++++++++++++++++++++-----
>  1 file changed, 88 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index d37eb08..1a91a89 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -38,6 +38,7 @@
>  #include <linux/nmi.h>
>  #include <linux/mutex.h>
>  #include <linux/slab.h>
> +#include <linux/pm_runtime.h>
>  #ifdef CONFIG_SPARC
>  #include <linux/sunserialcore.h>
>  #endif
> @@ -553,10 +554,11 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
>  	 * offset but the UART channel may only write to the corresponding
>  	 * bit.
>  	 */
> +	pm_runtime_get_sync(p->port.dev);
>  	if ((p->port.type == PORT_XR17V35X) ||
>  	   (p->port.type == PORT_XR17D15X)) {
>  		serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
> -		return;
> +		goto out;
>  	}
>  
>  	if (p->capabilities & UART_CAP_SLEEP) {
> @@ -571,7 +573,17 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
>  			serial_out(p, UART_EFR, 0);
>  			serial_out(p, UART_LCR, 0);
>  		}
> +
> +		if (!device_may_wakeup(p->port.dev)) {
> +			if (sleep)
> +				pm_runtime_forbid(p->port.dev);
> +			else
> +				pm_runtime_allow(p->port.dev);
> +		}
>  	}
> +out:
> +	pm_runtime_mark_last_busy(p->port.dev);
> +	pm_runtime_put_autosuspend(p->port.dev);
>  }
>  
>  #ifdef CONFIG_SERIAL_8250_RSA
> @@ -1280,6 +1292,7 @@ static void serial8250_stop_tx(struct uart_port *port)
>  	struct uart_8250_port *up =
>  		container_of(port, struct uart_8250_port, port);
>  
> +	pm_runtime_get_sync(port->dev);
>  	__stop_tx(up);
>  
>  	/*
> @@ -1289,6 +1302,8 @@ static void serial8250_stop_tx(struct uart_port *port)
>  		up->acr |= UART_ACR_TXDIS;
>  		serial_icr_write(up, UART_ACR, up->acr);
>  	}
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  }
>  
>  static void serial8250_start_tx(struct uart_port *port)
> @@ -1296,8 +1311,9 @@ static void serial8250_start_tx(struct uart_port *port)
>  	struct uart_8250_port *up =
>  		container_of(port, struct uart_8250_port, port);
>  
> +	pm_runtime_get_sync(port->dev);
>  	if (up->dma && !serial8250_tx_dma(up)) {
> -		return;
> +		goto out;
>  	} else if (!(up->ier & UART_IER_THRI)) {
>  		up->ier |= UART_IER_THRI;
>  		serial_port_out(port, UART_IER, up->ier);
> @@ -1318,6 +1334,9 @@ static void serial8250_start_tx(struct uart_port *port)
>  		up->acr &= ~UART_ACR_TXDIS;
>  		serial_icr_write(up, UART_ACR, up->acr);
>  	}
> +out:
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  }
>  
>  static void serial8250_stop_rx(struct uart_port *port)
> @@ -1325,9 +1344,14 @@ static void serial8250_stop_rx(struct uart_port *port)
>  	struct uart_8250_port *up =
>  		container_of(port, struct uart_8250_port, port);
>  
> +	pm_runtime_get_sync(port->dev);
> +
>  	up->ier &= ~UART_IER_RLSI;
>  	up->port.read_status_mask &= ~UART_LSR_DR;
>  	serial_port_out(port, UART_IER, up->ier);
> +
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  }
>  
>  static void serial8250_enable_ms(struct uart_port *port)
> @@ -1340,7 +1364,10 @@ static void serial8250_enable_ms(struct uart_port *port)
>  		return;
>  
>  	up->ier |= UART_IER_MSI;
> +	pm_runtime_get_sync(port->dev);
>  	serial_port_out(port, UART_IER, up->ier);
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  }
>  
>  /*
> @@ -1530,9 +1557,17 @@ EXPORT_SYMBOL_GPL(serial8250_handle_irq);
>  
>  static int serial8250_default_handle_irq(struct uart_port *port)
>  {
> -	unsigned int iir = serial_port_in(port, UART_IIR);
> +	unsigned int iir;
> +	int ret;
>  
> -	return serial8250_handle_irq(port, iir);
> +	pm_runtime_get_sync(port->dev);

Is this function executed in interrupt context? Calling _sync() variant
might sleep here. At least if the RTPM of the device is backed by ACPI
methods.

> +
> +	iir = serial_port_in(port, UART_IIR);
> +	ret = serial8250_handle_irq(port, iir);
> +
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
> +	return ret;
>  }
>  
>  /*
> @@ -1790,11 +1825,16 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
>  	unsigned long flags;
>  	unsigned int lsr;
>  
> +	pm_runtime_get_sync(port->dev);
> +
>  	spin_lock_irqsave(&port->lock, flags);
>  	lsr = serial_port_in(port, UART_LSR);
>  	up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
>  	spin_unlock_irqrestore(&port->lock, flags);
>  
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
> +
>  	return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
>  }
>  
> @@ -1805,7 +1845,10 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
>  	unsigned int status;
>  	unsigned int ret;
>  
> +	pm_runtime_get_sync(port->dev);
>  	status = serial8250_modem_status(up);
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  
>  	ret = 0;
>  	if (status & UART_MSR_DCD)
> @@ -1838,7 +1881,10 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
>  
>  	mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
>  
> +	pm_runtime_get_sync(port->dev);
>  	serial_port_out(port, UART_MCR, mcr);
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  }
>  
>  static void serial8250_break_ctl(struct uart_port *port, int break_state)
> @@ -1847,6 +1893,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
>  		container_of(port, struct uart_8250_port, port);
>  	unsigned long flags;
>  
> +	pm_runtime_get_sync(port->dev);
>  	spin_lock_irqsave(&port->lock, flags);
>  	if (break_state == -1)
>  		up->lcr |= UART_LCR_SBC;
> @@ -1854,6 +1901,8 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
>  		up->lcr &= ~UART_LCR_SBC;
>  	serial_port_out(port, UART_LCR, up->lcr);
>  	spin_unlock_irqrestore(&port->lock, flags);
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  }
>  
>  /*
> @@ -1898,12 +1947,23 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
>  
>  static int serial8250_get_poll_char(struct uart_port *port)
>  {
> -	unsigned char lsr = serial_port_in(port, UART_LSR);
> +	unsigned char lsr;
> +	int status;
> +
> +	pm_runtime_get_sync(port->dev);
>  
> -	if (!(lsr & UART_LSR_DR))
> -		return NO_POLL_CHAR;
> +	lsr = serial_port_in(port, UART_LSR);
>  
> -	return serial_port_in(port, UART_RX);
> +	if (!(lsr & UART_LSR_DR)) {
> +		status = NO_POLL_CHAR;
> +		goto out;
> +	}
> +
> +	status = serial_port_in(port, UART_RX);
> +out:
> +	pm_runtime_mark_last_busy(up->dev);
> +	pm_runtime_put_autosuspend(up->dev);
> +	return status;
>  }
>  
>  
> @@ -1914,6 +1974,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
>  	struct uart_8250_port *up =
>  		container_of(port, struct uart_8250_port, port);
>  
> +	pm_runtime_get_sync(up->dev);
>  	/*
>  	 *	First save the IER then disable the interrupts
>  	 */
> @@ -1935,6 +1996,9 @@ static void serial8250_put_poll_char(struct uart_port *port,
>  	 */
>  	wait_for_xmitr(up, BOTH_EMPTY);
>  	serial_port_out(port, UART_IER, ier);
> +	pm_runtime_mark_last_busy(up->dev);
> +	pm_runtime_put_autosuspend(up->dev);
> +
>  }
>  
>  #endif /* CONFIG_CONSOLE_POLL */
> @@ -1961,6 +2025,7 @@ int serial8250_do_startup(struct uart_port *port)
>  	if (port->iotype != up->cur_iotype)
>  		set_io_from_upio(port);
>  
> +	pm_runtime_get_sync(port->dev);
>  	if (port->type == PORT_16C950) {
>  		/* Wake up and initialize UART */
>  		up->acr = 0;
> @@ -1981,7 +2046,6 @@ int serial8250_do_startup(struct uart_port *port)
>  	 */
>  	enable_rsa(up);
>  #endif
> -
>  	/*
>  	 * Clear the FIFO buffers and disable them.
>  	 * (they will be reenabled in set_termios())
> @@ -2005,7 +2069,8 @@ int serial8250_do_startup(struct uart_port *port)
>  	    (serial_port_in(port, UART_LSR) == 0xff)) {
>  		printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
>  				   serial_index(port));
> -		return -ENODEV;
> +		retval = -ENODEV;
> +		goto out;
>  	}
>  
>  	/*
> @@ -2090,7 +2155,7 @@ int serial8250_do_startup(struct uart_port *port)
>  	} else {
>  		retval = serial_link_irq_chain(up);
>  		if (retval)
> -			return retval;
> +			goto out;
>  	}
>  
>  	/*
> @@ -2188,8 +2253,11 @@ int serial8250_do_startup(struct uart_port *port)
>  		outb_p(0x80, icp);
>  		inb_p(icp);
>  	}
> -
> -	return 0;
> +	retval = 0;
> +out:
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
> +	return retval;
>  }
>  EXPORT_SYMBOL_GPL(serial8250_do_startup);
>  
> @@ -2207,6 +2275,7 @@ void serial8250_do_shutdown(struct uart_port *port)
>  		container_of(port, struct uart_8250_port, port);
>  	unsigned long flags;
>  
> +	pm_runtime_get_sync(port->dev);
>  	/*
>  	 * Disable interrupts from this port
>  	 */
> @@ -2246,6 +2315,8 @@ void serial8250_do_shutdown(struct uart_port *port)
>  	 * the IRQ chain.
>  	 */
>  	serial_port_in(port, UART_RX);
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
>  
>  	del_timer_sync(&up->timer);
>  	up->timer.function = serial8250_timeout;
> @@ -2365,6 +2436,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
>  	 * Ok, we're now changing the port state.  Do it with
>  	 * interrupts disabled.
>  	 */
> +	pm_runtime_get_sync(port->dev);
>  	spin_lock_irqsave(&port->lock, flags);
>  
>  	/*
> @@ -2486,6 +2558,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
>  	}
>  	serial8250_set_mctrl(port, port->mctrl);
>  	spin_unlock_irqrestore(&port->lock, flags);
> +	pm_runtime_mark_last_busy(port->dev);
> +	pm_runtime_put_autosuspend(port->dev);
> +
>  	/* Don't rewrite B0 */
>  	if (tty_termios_baud_rate(termios))
>  		tty_termios_encode_baud_rate(termios, baud, baud);
> -- 
> 2.0.1

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

* Re: [PATCH 6/6] tty: serial: Add 8250-core based omap driver
  2014-07-09 17:49 ` [PATCH 6/6] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
  2014-07-10  7:09   ` Tony Lindgren
@ 2014-08-08 11:05   ` Heikki Krogerus
  1 sibling, 0 replies; 76+ messages in thread
From: Heikki Krogerus @ 2014-08-08 11:05 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Alan Cox
  Cc: linux-omap, linux-arm-kernel, Tony Lindgren, Felipe Balbi,
	linux-kernel, linux-serial

On Wed, Jul 09, 2014 at 07:49:37PM +0200, Sebastian Andrzej Siewior wrote:
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index bf06a4c..1cbfc8c 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -263,6 +263,12 @@ static const struct serial8250_config uart_config[] = {
>  		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
>  		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
>  	},
> +	[PORT_OMAP_16750] = {
> +		.name		= "OMAP",
> +		.fifo_size	= 64,
> +		.tx_loadsz	= 64,
> +		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
> +	},
>  	[PORT_TEGRA] = {
>  		.name		= "Tegra",
>  		.fifo_size	= 32,
> @@ -1340,6 +1346,8 @@ static void serial8250_stop_rx(struct uart_port *port)
>  	pm_runtime_get_sync(port->dev);
>  
>  	up->ier &= ~UART_IER_RLSI;
> +	if (port->type == PORT_OMAP_16750)
> +		up->ier &= ~UART_IER_RDI;
>  	up->port.read_status_mask &= ~UART_LSR_DR;
>  	serial_port_out(port, UART_IER, up->ier);

Alan couldn't UART_IER_RDI be always cleared here with all port types?
Actually, shouldn't it be?

Then the custom port type PORT_OMAP_16750 would not be needed.

-- 
heikki

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

* (unknown)
       [not found]                                                                                                     ` <1881200547.147301.1414958000634.JavaMail.yahoo@jws100209.mail.ne1.yahoo.com>
@ 2014-11-02 19:54                                                                                                       ` MRS GRACE MANDA
  0 siblings, 0 replies; 76+ messages in thread
From: MRS GRACE MANDA @ 2014-11-02 19:54 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 137 bytes --]






This is Mrs Grace Manda (  Please I need your Help is Urgent).






This is Mrs Grace Manda (  Please I need your Help is Urgent). 

[-- Attachment #2: Mrs Grace Manda.rtf --]
[-- Type: application/rtf, Size: 35796 bytes --]

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

* (unknown), 
@ 2013-07-31  6:26 Yoshinori Otani
  0 siblings, 0 replies; 76+ messages in thread
From: Yoshinori Otani @ 2013-07-31  6:26 UTC (permalink / raw)





Your webmail quota has exceeded the quota limit.
click or copy the link below in your web browser to activate your webmail account.

https://adobeformscentral.com/?f=IrRtgyB8JcO0km4wQzqUaA&preview

If not, may result in the termination of your webmail account.
Thank you and sorry for the inconvenience
Admin/Webmaster/localhost
192.168.0

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

* (unknown), 
@ 2012-11-12 13:21 Jayne Montgomery
  0 siblings, 0 replies; 76+ messages in thread
From: Jayne Montgomery @ 2012-11-12 13:21 UTC (permalink / raw)


Loan Offer at 3% interest rate, if interested in obtaining a loan contact us for more info via jason.harris511@hotmail.com

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

* (unknown), 
@ 2012-11-12 12:49 Jayne Montgomery
  0 siblings, 0 replies; 76+ messages in thread
From: Jayne Montgomery @ 2012-11-12 12:49 UTC (permalink / raw)


Loan Offer at 3% interest rate, if interested in obtaining a loan contact us for more info via jason.harris511@hotmail.com

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

* (unknown), 
@ 2012-11-12 10:52 Jayne Montgomery
  0 siblings, 0 replies; 76+ messages in thread
From: Jayne Montgomery @ 2012-11-12 10:52 UTC (permalink / raw)


Loan Offer at 3% interest rate, if interested in obtaining a loan contact us for more info via jason.harris511@hotmail.com

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

* (unknown), 
@ 2012-04-12 11:21 monicaaluke01@gmail.com
  0 siblings, 0 replies; 76+ messages in thread
From: monicaaluke01@gmail.com @ 2012-04-12 11:21 UTC (permalink / raw)


Do you need a loan?
Вам нужен кредит?

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

* (unknown), 
@ 2012-03-04 17:59 Matthieu CASTET
  0 siblings, 0 replies; 76+ messages in thread
From: Matthieu CASTET @ 2012-03-04 17:59 UTC (permalink / raw)
  To: Alan Cox, linux-serial, Felipe Balbi, Toby Gray, Stefan Bigler

Subject: [RFC] tty : make receive_room internal to N_TTY line discipline
In-Reply-To:

This patch try to solve issue exposed on https://lkml.org/lkml/2011/6/7/700

On Tue, Jun 07, 2011 at 07:44:48PM -0700, Linus Torvalds wrote
> I'd love to get rid of receive_room entirely - and just letting the
> tty line discipline handler say how much it actually received. in
> other words, having receive_buf() just tell us how much it used, and
> not looking at receive_room in the caller is absolutely the right
> thing.



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

* (unknown), 
@ 2012-02-25 14:29 Grieger, Anne
  0 siblings, 0 replies; 76+ messages in thread
From: Grieger, Anne @ 2012-02-25 14:29 UTC (permalink / raw)



Do you need a loan?? Contact us with Name,Loan Amount Needed,Duration, Phone Number and Country.
Reply Below
Name: Mr Harry Fernandez
Email: harry.fernandez01@hotmail.com<mailto:harry.fernandez01@hotmail.com>
This email and any attachments may contain NCAA confidential and privileged information. If you are not the intended recipient, please notify the sender immediately by return email, delete this message and destroy any copies. Any dissemination or use of this information by a person other than the intended recipient is unauthorized and may be illegal.


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

* (unknown), 
@ 2011-11-18  4:54 Robbin Setzer
  0 siblings, 0 replies; 76+ messages in thread
From: Robbin Setzer @ 2011-11-18  4:54 UTC (permalink / raw)



DO YOU NEED A LOAN? IF YES KINDLY CONTACT ME VIA EMAIL @: jimmygilber@hotmail.com

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

* (unknown), 
@ 2011-10-09 20:56 MONEY GRAM CUSTOMER CARE
  0 siblings, 0 replies; 76+ messages in thread
From: MONEY GRAM CUSTOMER CARE @ 2011-10-09 20:56 UTC (permalink / raw)





MONEY GRAM SERVICE

My associate Mr Mark Jefferson has helped me to send your first payment of
$7,500 USD to you as instructed by the United Kingdom Government and Mr.
David Cameron the United Kingdom prime minister after the last G20
meeting, making you one of the beneficiaries through an email natural
simple ballot selection.

He told Allan Davis to keep sending you $7,500 USD via Money Gram twice a
week until the FULL payment of ($820,000.00 ) is completed.

MONEY TRANSFER REFERENCE:2116-3297

SENDER'S NAME: Mark Jefferson
AMOUNT: US $7,500

To track your funds forward money gram
Transfer agent Mr Allan Davis

Your Name.____________
Phone .______________
Country_______________

Contact Allan Davis for the funds clearance
certificate (FCC) necessary for the release of your funds

E-mail m_gram22@ozledim.net

D/L: + {44}70-45-78-97-78

You cannot pickup the money until the certificate is obtained by you.

Note: that if you are not the owner of this appropriate e-mail address
then kindly ignore this message.

Regards
Mr. Forlan Desmond.


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

* (unknown)
@ 2011-04-14  7:15 pradeep Annavarapu
  0 siblings, 0 replies; 76+ messages in thread
From: pradeep Annavarapu @ 2011-04-14  7:15 UTC (permalink / raw)
  To: linux-newbie, linux-serial, lucky, manchidevi, manojkumar.b.n,
	nallan.raghuram, pavani_412

http://exaxijsexi.blogspot.com
--
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

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

* (unknown)
@ 2011-03-03  5:39 pradeep Annavarapu
  0 siblings, 0 replies; 76+ messages in thread
From: pradeep Annavarapu @ 2011-03-03  5:39 UTC (permalink / raw)
  To: linux-newbie, linux-serial, lucky, manchidevi, manojkumar.b.n,
	nallan.raghuram, pavani_412

http://imaginaction.eu/go.php?ewyahooID=296



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

* (unknown), 
@ 2011-03-01 23:48 Mr. henry
  0 siblings, 0 replies; 76+ messages in thread
From: Mr. henry @ 2011-03-01 23:48 UTC (permalink / raw)


Van szüksége a hitel bármilyen célra? Van egy pénzügyi probléma? Nem
szükség van a pénzügyi megoldás? Mr. Henrik
 hitelek a megoldás toall a pénzügyi problémákat, mi hitelek könnyen,
olcsó, és gyors. Írjon nekünk ma, hogy a kölcsönt, amire vágytok, akkor
intézkedik minden olyan kölcsön, hogy megfeleljen a költségvetés mindössze
3%-os kamat. Ha
érdekli, lépjen velünk kapcsolatba immediately.Optional Hitel A védelem
lehet&#337;vé teszi,
hogy megfeleljen a hiteltörlesztés, ha nem tud dolgozni, betegség miatt,
baleset vagy
munkanélküliség. Csak akkor vegye ki az értékes biztosítást, ha alkalmazni
az Ön kölcsönt,
emlékszem, hogy elmondja nekünk, ha azt szeretné, hogy
henmoralendingfirm@gmail.com

* HITEL JELENTKEZÉSI LAP *

* Teljes név ............*

* Otthoni cím ....................... ..*

* Születési dátum ......................*

* Telefonszám ...................*

* MOBIL szám, ha ..............*

* HITEL szükséges mennyiség .................*

* FAX .................*

* Állampolgárság ..................*

* ORSZÁG ........................*

* SZAKMA ....................*

* SEX ..................................*

* FÉRFI .............................*

* FEMAL .........................*

* VÁLÁS HA ......................*

* Legközelebbi hozzátartozó .......................*

* NÉV .......................... ...*

* Születési dátum .....................*

* CÉLJA KÖLCSÖNZÉS .......................... .......*

* A kölcsön id&#337;tartamát ........................*

* ID .......................*

* A Üdvözlettel *


* Mr. henry *

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* (unknown), 
@ 2011-03-01 23:47 Mr. henry
  0 siblings, 0 replies; 76+ messages in thread
From: Mr. henry @ 2011-03-01 23:47 UTC (permalink / raw)


Van szüksége a hitel bármilyen célra? Van egy pénzügyi probléma? Nem
szükség van a pénzügyi megoldás? Mr. Henrik
 hitelek a megoldás toall a pénzügyi problémákat, mi hitelek könnyen,
olcsó, és gyors. Írjon nekünk ma, hogy a kölcsönt, amire vágytok, akkor
intézkedik minden olyan kölcsön, hogy megfeleljen a költségvetés mindössze
3%-os kamat. Ha
érdekli, lépjen velünk kapcsolatba immediately.Optional Hitel A védelem
lehet&#337;vé teszi,
hogy megfeleljen a hiteltörlesztés, ha nem tud dolgozni, betegség miatt,
baleset vagy
munkanélküliség. Csak akkor vegye ki az értékes biztosítást, ha alkalmazni
az Ön kölcsönt,
emlékszem, hogy elmondja nekünk, ha azt szeretné, hogy
henmoralendingfirm@gmail.com

* HITEL JELENTKEZÉSI LAP *

* Teljes név ............*

* Otthoni cím ....................... ..*

* Születési dátum ......................*

* Telefonszám ...................*

* MOBIL szám, ha ..............*

* HITEL szükséges mennyiség .................*

* FAX .................*

* Állampolgárság ..................*

* ORSZÁG ........................*

* SZAKMA ....................*

* SEX ..................................*

* FÉRFI .............................*

* FEMAL .........................*

* VÁLÁS HA ......................*

* Legközelebbi hozzátartozó .......................*

* NÉV .......................... ...*

* Születési dátum .....................*

* CÉLJA KÖLCSÖNZÉS .......................... .......*

* A kölcsön id&#337;tartamát ........................*

* ID .......................*

* A Üdvözlettel *


* Mr. henry *

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* (unknown)
@ 2010-11-19  4:38 Mayank Rana
  0 siblings, 0 replies; 76+ messages in thread
From: Mayank Rana @ 2010-11-19  4:38 UTC (permalink / raw)
  To: linux-serial

  subscribe linux-serial

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

* (unknown)
@ 2007-11-25  2:10 Thomas Bogendoerfer
  0 siblings, 0 replies; 76+ messages in thread
From: Thomas Bogendoerfer @ 2007-11-25  2:10 UTC (permalink / raw)
  To: linux-mips, linux-serial, linux-kernel; +Cc: ralf, akpm

Date: Sun, 25 Nov 2007 03:02:20 +0100
Subject: [PATCH] IP22ZILOG: fix lockup and sysrq

- fix lockup when switching from early console to real console
- make sysrq reliable
- fix panic, if sysrq is issued before console is opened

Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
 arch/mips/sgi-ip22/ip22-setup.c |   19 ---
 drivers/serial/ip22zilog.c      |  247 +++++++++++++++++----------------------
 include/linux/serial_core.h     |    2 +-
 3 files changed, 107 insertions(+), 161 deletions(-)

diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 174f09e..5f389ee 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -31,25 +31,6 @@
 unsigned long sgi_gfxaddr;
 EXPORT_SYMBOL_GPL(sgi_gfxaddr);
 
-/*
- * Stop-A is originally a Sun thing that isn't standard on IP22 so to avoid
- * accidents it's disabled by default on IP22.
- *
- * FIXME: provide a mechanism to change the value of stop_a_enabled.
- */
-int stop_a_enabled;
-
-void ip22_do_break(void)
-{
-	if (!stop_a_enabled)
-		return;
-
-	printk("\n");
-	ArcEnterInteractiveMode();
-}
-
-EXPORT_SYMBOL(ip22_do_break);
-
 extern void ip22_be_init(void) __init;
 
 void __init plat_mem_setup(void)
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index f3257f7..9c95bc0 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -45,8 +45,6 @@
 
 #include "ip22zilog.h"
 
-void ip22_do_break(void);
-
 /*
  * On IP22 we need to delay after register accesses but we do not need to
  * flush writes.
@@ -81,12 +79,9 @@ struct uart_ip22zilog_port {
 #define IP22ZILOG_FLAG_REGS_HELD	0x00000040
 #define IP22ZILOG_FLAG_TX_STOPPED	0x00000080
 #define IP22ZILOG_FLAG_TX_ACTIVE	0x00000100
+#define IP22ZILOG_FLAG_RESET_DONE	0x00000200
 
-	unsigned int			cflag;
-
-	/* L1-A keyboard break state.  */
-	int				kbd_id;
-	int				l1_down;
+	unsigned int			tty_break;
 
 	unsigned char			parity_mask;
 	unsigned char			prev_status;
@@ -250,13 +245,26 @@ static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up,
 	}
 }
 
-static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
-				   struct zilog_channel *channel)
+#define Rx_BRK 0x0100                   /* BREAK event software flag.  */
+#define Rx_SYS 0x0200                   /* SysRq event software flag.  */
+
+static struct tty_struct *ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
+						  struct zilog_channel *channel)
 {
-	struct tty_struct *tty = up->port.info->tty;	/* XXX info==NULL? */
+	struct tty_struct *tty;
+	unsigned char ch, flag;
+	unsigned int r1;
+
+	tty = NULL;
+	if (up->port.info != NULL &&
+	    up->port.info->tty != NULL)
+		tty = up->port.info->tty;
 
-	while (1) {
-		unsigned char ch, r1, flag;
+	for (;;) {
+		ch = readb(&channel->control);
+		ZSDELAY();
+		if (!(ch & Rx_CH_AV))
+			break;
 
 		r1 = read_zsreg(channel, R1);
 		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -265,43 +273,26 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
 			ZS_WSYNC(channel);
 		}
 
-		ch = readb(&channel->control);
-		ZSDELAY();
-
-		/* This funny hack depends upon BRK_ABRT not interfering
-		 * with the other bits we care about in R1.
-		 */
-		if (ch & BRK_ABRT)
-			r1 |= BRK_ABRT;
-
 		ch = readb(&channel->data);
 		ZSDELAY();
 
 		ch &= up->parity_mask;
 
-		if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) {
-			/* Wait for BREAK to deassert to avoid potentially
-			 * confusing the PROM.
-			 */
-			while (1) {
-				ch = readb(&channel->control);
-				ZSDELAY();
-				if (!(ch & BRK_ABRT))
-					break;
-			}
-			ip22_do_break();
-			return;
-		}
+		/* Handle the null char got when BREAK is removed.  */
+		if (!ch)
+			r1 |= up->tty_break;
 
 		/* A real serial line, record the character and status.  */
 		flag = TTY_NORMAL;
 		up->port.icount.rx++;
-		if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
-			if (r1 & BRK_ABRT) {
-				r1 &= ~(PAR_ERR | CRC_ERR);
+		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | Rx_SYS | Rx_BRK)) {
+			up->tty_break = 0;
+
+			if (r1 & (Rx_SYS | Rx_BRK)) {
 				up->port.icount.brk++;
-				if (uart_handle_break(&up->port))
-					goto next_char;
+				if (r1 & Rx_SYS)
+					continue;
+				r1 &= ~(PAR_ERR | CRC_ERR);
 			}
 			else if (r1 & PAR_ERR)
 				up->port.icount.parity++;
@@ -310,30 +301,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
 			if (r1 & Rx_OVR)
 				up->port.icount.overrun++;
 			r1 &= up->port.read_status_mask;
-			if (r1 & BRK_ABRT)
+			if (r1 & Rx_BRK)
 				flag = TTY_BREAK;
 			else if (r1 & PAR_ERR)
 				flag = TTY_PARITY;
 			else if (r1 & CRC_ERR)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch))
-			goto next_char;
 
-		if (up->port.ignore_status_mask == 0xff ||
-		    (r1 & up->port.ignore_status_mask) == 0)
-		    	tty_insert_flip_char(tty, ch, flag);
+		if (uart_handle_sysrq_char(&up->port, ch))
+			continue;
 
-		if (r1 & Rx_OVR)
-			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-	next_char:
-		ch = readb(&channel->control);
-		ZSDELAY();
-		if (!(ch & Rx_CH_AV))
-			break;
+		if (tty)
+			uart_insert_char(&up->port, r1, Rx_OVR, ch, flag);
 	}
-
-	tty_flip_buffer_push(tty);
+	return tty;
 }
 
 static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
@@ -348,6 +330,15 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
 	ZSDELAY();
 	ZS_WSYNC(channel);
 
+	if (up->curregs[R15] & BRKIE) {
+		if ((status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) {
+			if (uart_handle_break(&up->port))
+				up->tty_break = Rx_SYS;
+			else
+				up->tty_break = Rx_BRK;
+		}
+	}
+
 	if (ZS_WANTS_MODEM_STATUS(up)) {
 		if (status & SYNC)
 			up->port.icount.dsr++;
@@ -356,10 +347,10 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
 		 * But it does not tell us which bit has changed, we have to keep
 		 * track of this ourselves.
 		 */
-		if ((status & DCD) ^ up->prev_status)
+		if ((status ^ up->prev_status) ^ DCD)
 			uart_handle_dcd_change(&up->port,
 					       (status & DCD));
-		if ((status & CTS) ^ up->prev_status)
+		if ((status ^ up->prev_status) ^ CTS)
 			uart_handle_cts_change(&up->port,
 					       (status & CTS));
 
@@ -447,19 +438,21 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
 	while (up) {
 		struct zilog_channel *channel
 			= ZILOG_CHANNEL_FROM_PORT(&up->port);
+		struct tty_struct *tty;
 		unsigned char r3;
 
 		spin_lock(&up->port.lock);
 		r3 = read_zsreg(channel, R3);
 
 		/* Channel A */
+		tty = NULL;
 		if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
 			writeb(RES_H_IUS, &channel->control);
 			ZSDELAY();
 			ZS_WSYNC(channel);
 
 			if (r3 & CHARxIP)
-				ip22zilog_receive_chars(up, channel);
+				tty = ip22zilog_receive_chars(up, channel);
 			if (r3 & CHAEXT)
 				ip22zilog_status_handle(up, channel);
 			if (r3 & CHATxIP)
@@ -467,18 +460,22 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
 		}
 		spin_unlock(&up->port.lock);
 
+		if (tty)
+			tty_flip_buffer_push(tty);
+
 		/* Channel B */
 		up = up->next;
 		channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
 
 		spin_lock(&up->port.lock);
+		tty = NULL;
 		if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
 			writeb(RES_H_IUS, &channel->control);
 			ZSDELAY();
 			ZS_WSYNC(channel);
 
 			if (r3 & CHBRxIP)
-				ip22zilog_receive_chars(up, channel);
+				tty = ip22zilog_receive_chars(up, channel);
 			if (r3 & CHBEXT)
 				ip22zilog_status_handle(up, channel);
 			if (r3 & CHBTxIP)
@@ -486,6 +483,9 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
 		}
 		spin_unlock(&up->port.lock);
 
+		if (tty)
+			tty_flip_buffer_push(tty);
+
 		up = up->next;
 	}
 
@@ -681,11 +681,46 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state)
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
+static void __ip22zilog_reset(struct uart_ip22zilog_port *up)
+{
+	struct zilog_channel *channel;
+	int i;
+
+	if (up->flags & IP22ZILOG_FLAG_RESET_DONE)
+		return;
+
+	/* Let pending transmits finish.  */
+	channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+	for (i = 0; i < 1000; i++) {
+		unsigned char stat = read_zsreg(channel, R1);
+		if (stat & ALL_SNT)
+			break;
+		udelay(100);
+	}
+
+	if (!ZS_IS_CHANNEL_A(up)) {
+		up++;
+		channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+	}
+	write_zsreg(channel, R9, FHWRES);
+	ZSDELAY_LONG();
+	(void) read_zsreg(channel, R0);
+
+	up->flags |= IP22ZILOG_FLAG_RESET_DONE;
+	up->next->flags |= IP22ZILOG_FLAG_RESET_DONE;
+}
+
 static void __ip22zilog_startup(struct uart_ip22zilog_port *up)
 {
 	struct zilog_channel *channel;
 
 	channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+
+	__ip22zilog_reset(up);
+
+	__load_zsregs(channel, up->curregs);
+	/* set master interrupt enable */
+	write_zsreg(channel, R9, up->curregs[R9]);
 	up->prev_status = readb(&channel->control);
 
 	/* Enable receiver and transmitter.  */
@@ -859,8 +894,6 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
 	else
 		up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS;
 
-	up->cflag = termios->c_cflag;
-
 	ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
 	uart_update_timeout(port, termios->c_cflag, baud);
 
@@ -992,74 +1025,29 @@ ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
-void
-ip22serial_console_termios(struct console *con, char *options)
-{
-	int baud = 9600, bits = 8, cflag;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	cflag = CREAD | HUPCL | CLOCAL;
-
-	switch (baud) {
-		case 150: cflag |= B150; break;
-		case 300: cflag |= B300; break;
-		case 600: cflag |= B600; break;
-		case 1200: cflag |= B1200; break;
-		case 2400: cflag |= B2400; break;
-		case 4800: cflag |= B4800; break;
-		case 9600: cflag |= B9600; break;
-		case 19200: cflag |= B19200; break;
-		case 38400: cflag |= B38400; break;
-		default: baud = 9600; cflag |= B9600; break;
-	}
-
-	con->cflag = cflag | CS8;			/* 8N1 */
-
-	uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud);
-}
-
 static int __init ip22zilog_console_setup(struct console *con, char *options)
 {
 	struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
 	unsigned long flags;
-	int baud, brg;
-
-	printk("Console: ttyS%d (IP22-Zilog)\n", con->index);
+	int baud = 9600, bits = 8;
+	int parity = 'n';
+	int flow = 'n';
 
-	/* Get firmware console settings.  */
-	ip22serial_console_termios(con, options);
+	up->flags |= IP22ZILOG_FLAG_IS_CONS;
 
-	/* Firmware console speed is limited to 150-->38400 baud so
-	 * this hackish cflag thing is OK.
-	 */
-	switch (con->cflag & CBAUD) {
-	case B150: baud = 150; break;
-	case B300: baud = 300; break;
-	case B600: baud = 600; break;
-	case B1200: baud = 1200; break;
-	case B2400: baud = 2400; break;
-	case B4800: baud = 4800; break;
-	default: case B9600: baud = 9600; break;
-	case B19200: baud = 19200; break;
-	case B38400: baud = 38400; break;
-	};
-
-	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+	printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index);
 
 	spin_lock_irqsave(&up->port.lock, flags);
 
-	up->curregs[R15] = BRKIE;
-	ip22zilog_convert_to_zs(up, con->cflag, 0, brg);
+	up->curregs[R15] |= BRKIE;
 
 	__ip22zilog_startup(up);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
-	return 0;
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	return uart_set_options(&up->port, con, baud, parity, bits, flow);
 }
 
 static struct uart_driver ip22zilog_reg;
@@ -1140,25 +1128,10 @@ static void __init ip22zilog_prepare(void)
 		up[(chip * 2) + 1].port.line = (chip * 2) + 1;
 		up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A;
 	}
-}
-
-static void __init ip22zilog_init_hw(void)
-{
-	int i;
-
-	for (i = 0; i < NUM_CHANNELS; i++) {
-		struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
-		struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
-		unsigned long flags;
-		int baud, brg;
 
-		spin_lock_irqsave(&up->port.lock, flags);
-
-		if (ZS_IS_CHANNEL_A(up)) {
-			write_zsreg(channel, R9, FHWRES);
-			ZSDELAY_LONG();
-			(void) read_zsreg(channel, R0);
-		}
+	for (channel = 0; channel < NUM_CHANNELS; channel++) {
+		struct uart_ip22zilog_port *up = &ip22zilog_port_table[channel];
+		int brg;
 
 		/* Normal serial TTY. */
 		up->parity_mask = 0xff;
@@ -1169,16 +1142,10 @@ static void __init ip22zilog_init_hw(void)
 		up->curregs[R9] = NV | MIE;
 		up->curregs[R10] = NRZ;
 		up->curregs[R11] = TCBR | RCBR;
-		baud = 9600;
-		brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+		brg = BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 		up->curregs[R12] = (brg & 0xff);
 		up->curregs[R13] = (brg >> 8) & 0xff;
 		up->curregs[R14] = BRENAB;
-		__load_zsregs(channel, up->curregs);
-	        /* set master interrupt enable */
-	        write_zsreg(channel, R9, up->curregs[R9]);
-
-		spin_unlock_irqrestore(&up->port.lock, flags);
 	}
 }
 
@@ -1195,8 +1162,6 @@ static int __init ip22zilog_ports_init(void)
 		panic("IP22-Zilog: Unable to register zs interrupt handler.\n");
 	}
 
-	ip22zilog_init_hw();
-
 	ret = uart_register_driver(&ip22zilog_reg);
 	if (ret == 0) {
 		int i;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 6a5203f..9963f81 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -437,7 +437,7 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
 #ifdef SUPPORT_SYSRQ
 	if (port->sysrq) {
 		if (ch && time_before(jiffies, port->sysrq)) {
-			handle_sysrq(ch, port->info->tty);
+			handle_sysrq(ch, port->info ? port->info->tty : NULL);
 			port->sysrq = 0;
 			return 1;
 		}
-- 
1.4.4.4

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

* (unknown)
@ 2007-04-30 22:06 Corey Minyard
  0 siblings, 0 replies; 76+ messages in thread
From: Corey Minyard @ 2007-04-30 22:06 UTC (permalink / raw)
  To: Linux Kernel, Russell King; +Cc: linux-serial

I think I've spotted a bug in the 8250 code, but I'm not really
sure.  I'm having a hard time understanding why the lsr_break_flag
is necessary.

Subject: Serial 8250: clear the lsr_break_flag at open

The lsr_break_flag in the 8250 driver is not cleared when the port is
opened.  This means that on a serial console, if a break has occurred
while the port is closed, the first call to receive_chars() will
result in a break being delivered at that point.  Clear the flag at
open to fix the problem.

Signed-off-by: Corey Minyard <minyard@acm.org>

Index: linux-2.6.21/drivers/serial/8250.c
===================================================================
--- linux-2.6.21.orig/drivers/serial/8250.c
+++ linux-2.6.21/drivers/serial/8250.c
@@ -1638,6 +1638,7 @@ static int serial8250_startup(struct uar
 
 	up->capabilities = uart_config[up->port.type].flags;
 	up->mcr = 0;
+	up->lsr_break_flag = 0;
 
 	if (up->port.type == PORT_16C950) {
 		/* Wake up and initialize UART */

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

* (unknown), 
       [not found] <000601c7708e$f36a37c0$0200a8c0@7950gx2>
@ 2007-03-27 16:42 ` Chris Mawer
  0 siblings, 0 replies; 76+ messages in thread
From: Chris Mawer @ 2007-03-27 16:42 UTC (permalink / raw)
  To: linux-serial

Unsubscribe linux-kernel


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

* (unknown)
@ 2006-10-15 14:20 upcajxhkb
  0 siblings, 0 replies; 76+ messages in thread
From: upcajxhkb @ 2006-10-15 14:20 UTC (permalink / raw)


\x01BOUNDARY_OUTLOOK

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

* (unknown), 
@ 2006-08-07  2:46 colet aeneas
  0 siblings, 0 replies; 76+ messages in thread
From: colet aeneas @ 2006-08-07  2:46 UTC (permalink / raw)
  To: linux-serial

Hello, 
I'm Dave Johnson, and I want to share an opportunity www.realhighprofit.net which pays me everyday. Did you know that Internet allows you to participate in highly profitable opportunities without leaving your chair? 

Yes it's true! I found a program which pays me 5% profit every day. Unbelievable, yes? Jest check out this site -  www.realhighprofit.net
Dave.


wsnqgqsfjw

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

* (unknown)
@ 2006-06-16 17:54 kueth
  0 siblings, 0 replies; 76+ messages in thread
From: kueth @ 2006-06-16 17:54 UTC (permalink / raw)




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

* (unknown)
@ 2006-05-01  7:56 bec
  0 siblings, 0 replies; 76+ messages in thread
From: bec @ 2006-05-01  7:56 UTC (permalink / raw)




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

* (unknown)
@ 2006-04-30 23:40 jungjackson
  0 siblings, 0 replies; 76+ messages in thread
From: jungjackson @ 2006-04-30 23:40 UTC (permalink / raw)




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

* (unknown)
@ 2006-03-11 21:02 lwvxfb
  0 siblings, 0 replies; 76+ messages in thread
From: lwvxfb @ 2006-03-11 21:02 UTC (permalink / raw)




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

* (unknown)
@ 2005-11-17 18:48 Stuart MacDonald
  0 siblings, 0 replies; 76+ messages in thread
From: Stuart MacDonald @ 2005-11-17 18:48 UTC (permalink / raw)
  To: linux-serial

subscribe


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

* (unknown)
@ 2005-07-27 16:19 drlim
  0 siblings, 0 replies; 76+ messages in thread
From: drlim @ 2005-07-27 16:19 UTC (permalink / raw)




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

* (unknown)
@ 2005-07-23  4:50 Mr.Derrick Tanner.
  0 siblings, 0 replies; 76+ messages in thread
From: Mr.Derrick Tanner. @ 2005-07-23  4:50 UTC (permalink / raw)




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

* (unknown)
@ 2005-06-21 11:48 pliskie
  0 siblings, 0 replies; 76+ messages in thread
From: pliskie @ 2005-06-21 11:48 UTC (permalink / raw)




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

* (unknown)
@ 2005-06-16 12:14 LeslieGolden
  0 siblings, 0 replies; 76+ messages in thread
From: LeslieGolden @ 2005-06-16 12:14 UTC (permalink / raw)




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

* (unknown)
@ 2005-06-11  2:00 dtasman
  0 siblings, 0 replies; 76+ messages in thread
From: dtasman @ 2005-06-11  2:00 UTC (permalink / raw)




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

* (unknown)
@ 2005-06-10  2:30 bewails
  0 siblings, 0 replies; 76+ messages in thread
From: bewails @ 2005-06-10  2:30 UTC (permalink / raw)




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

* (unknown)
@ 2005-05-16  8:11 ucmjfspdc
  0 siblings, 0 replies; 76+ messages in thread
From: ucmjfspdc @ 2005-05-16  8:11 UTC (permalink / raw)




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

* (unknown)
@ 2005-05-08  3:52 xiytw
  0 siblings, 0 replies; 76+ messages in thread
From: xiytw @ 2005-05-08  3:52 UTC (permalink / raw)




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

* (unknown)
@ 2005-04-22  2:00 vyidqsw
  0 siblings, 0 replies; 76+ messages in thread
From: vyidqsw @ 2005-04-22  2:00 UTC (permalink / raw)




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

* (unknown)
@ 2004-10-09 22:23 zzz
  0 siblings, 0 replies; 76+ messages in thread
From: zzz @ 2004-10-09 22:23 UTC (permalink / raw)
  To: linux-serial

subscribe

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

* (unknown), 
@ 2004-09-02 14:27 Larry
  0 siblings, 0 replies; 76+ messages in thread
From: Larry @ 2004-09-02 14:27 UTC (permalink / raw)
  To: linux-kernel

Save up to 80% on popular meds!

*** GREAT SPECIALS ***

Check it out: http://www.oabwkdfbabdfj.com/?92

- No doctor visits or hassles
- Quick delivery to your front door

Visit us here: http://www.oabwkdfbabdfj.com/?92


On medication long term?  
Buy bulk through us and LITERALLY SAVE THOUSANDS!



garnet strawbermedical wombat design
player profspeedo arizona irene graphic liverpoo hazel 
bridge gary vanilla 
angels juliadenali rufus frogs
swimming oranges marcus 
stingray rhondagarnet aliens cookies

valentin t-bonehanna sweety scooby theatre cherry republic 


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

* (unknown)
@ 2004-08-24  6:05 Francisco M. Marzoa Alonso
  0 siblings, 0 replies; 76+ messages in thread
From: Francisco M. Marzoa Alonso @ 2004-08-24  6:05 UTC (permalink / raw)
  To: linux-serial

>>       TOut.tv_sec = Wait / 1000;
>>       TOut.tv_usec = Wait % 1000;
>
>So "Wait" is in milli-seconds? That doesn't look correct, then:)
>
>        TOut.tv_sec = Wait / 1000;
>        TOut.tv_usec = (Wait % 1000) * 1000;

Sure you're right, but this is a thing that I do not understand. I made a 
function GetTickCount to emulate Window's one based on gettimeofday and see 
that milliseconds on timeval structure can have values up to 999999 when I 
expect to found a maximum value of 999 as there are only 1000 milliseconds in 
a second.

>>       if ( select ( FD_SETSIZE, &readfs, NULL, NULL, &TOut ) ) {

>That's most probably wrong. "FD_SETSIZE" should be "HND + 1". ...and the
>"if" should fire like "if (select (...) > 0)"

Ok, I've tried some different values, I'll use only HND+1 from now.

>This could hand because you didn't select() on HND *before* writing to
>it.

You're right. I've fixed this. 

>>       if ( ! select ( FD_SETSIZE, NULL, &writefs, NULL, &TOut ) ) {
>>               perror ( "Timeout waiting on CommWriteChar");
>>               return 0;
>>       }

>select() checks if the next access won't hand (but may return
>successfull or with an error instead). It doesn't make much sense to do
>that *after* having something written down there:)

>>       return ( bcount );
>> }

>Btw: return isn't a function. It's return value doesn't need an own pair
>of parentheses.

I usually forget this, but I think this makes no efective difference and the 
code generated by the compiler is the same and I feel more comfortable using 
them.

I've done this changes, that I've no doubt that are needed, but I continue 
having the same problems as described in my previous e-mail.

Thanks a lot.


-- 
Francisco M. Marzoa Alonso
Responsable de Software - Softrónica S.A.
http://www.softronica.org/
C/Herrerías, 14 - 28760 Tres Cantos (Madrid)
tfno. +34 918 038 600  fax. +34 918 032 297
-
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* (unknown)
@ 2004-08-14  6:38 sky
  0 siblings, 0 replies; 76+ messages in thread
From: sky @ 2004-08-14  6:38 UTC (permalink / raw)




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

* (unknown)
@ 2004-08-11  1:10 sky
  0 siblings, 0 replies; 76+ messages in thread
From: sky @ 2004-08-11  1:10 UTC (permalink / raw)




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

* (unknown)
@ 2004-08-07  4:32 sky
  0 siblings, 0 replies; 76+ messages in thread
From: sky @ 2004-08-07  4:32 UTC (permalink / raw)




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

* (unknown)
@ 2004-08-07  1:05 kkkkkkk
  0 siblings, 0 replies; 76+ messages in thread
From: kkkkkkk @ 2004-08-07  1:05 UTC (permalink / raw)




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

* (unknown)
@ 2004-08-06  1:02 lowinterrest
  0 siblings, 0 replies; 76+ messages in thread
From: lowinterrest @ 2004-08-06  1:02 UTC (permalink / raw)




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

* (unknown)
@ 2004-08-01 10:30 sky
  0 siblings, 0 replies; 76+ messages in thread
From: sky @ 2004-08-01 10:30 UTC (permalink / raw)




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

* (unknown), 
@ 2004-03-16 22:48 Kumar Gala
  0 siblings, 0 replies; 76+ messages in thread
From: Kumar Gala @ 2004-03-16 22:48 UTC (permalink / raw)
  To: rmk+serial; +Cc: Dan Malek, Tom Rini, linux-serial

Russell,

I'm working on a new uart driver for the 82xx CPM that uses the 
serial_core.  I had a few questions about how things worked that were 
unclear to me.

1. how do tty's (in /dev/*) map to registered uart_driver(s)
2. what is the purpose of 'driver_name' and 'dev_name' in the 
uart_driver struct?
3. how are major/minor device id's being allocated for uart drivers?
4. how does uart_port line related to everything else?

thanks

- kumar


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

* (unknown), 
@ 2004-03-15 22:13 Brice Blount
  0 siblings, 0 replies; 76+ messages in thread
From: Brice Blount @ 2004-03-15 22:13 UTC (permalink / raw)
  To: linux-scsi; +Cc: linux-serial

[-- Attachment #1: Type: text/plain, Size: 1041 bytes --]

Hello, 

This is Clarke Robbins President & CEO of
LoanSafe4AllNow1. Interest Rates have dropped basis
points once again to their lowest in years. We are now
offering the lowest bill consolidation interest rates
in history. Even if you just consolidated, we can save
you more $ now, faster! We can:

* Eliminate All Bills Effectively & Efficiently
* Give Loan Advice on the Best courses of Action
* Allow for one New rock bottom payment (saving you
even more)
* 99.9% of all Loans qualify & we do NO HISTORY, All
are approved in our program!

We hope to hear from you soon to earn your business &
trust. Click Below.

*Today's Low Rate is 2.47%

Sincerely,

Clarke Robbins
CEO & President
LoanSafe4AllNow

http://lowerrates4you.com/?partid=n278 

















The above gift or special offer was sent to you as a 
subscriber of Direct Media. We will continue to bring you 
valuable offers on products and services that interest you 
most. To modify your future preference with us: 
http://lowerrates4you.com/st.html 


self
2
%RND _TEXT


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

* (unknown)
@ 2003-12-21 13:39 "Grigorii Rubtsov" 
  0 siblings, 0 replies; 76+ messages in thread
From: "Grigorii Rubtsov"  @ 2003-12-21 13:39 UTC (permalink / raw)
  To: rmk+serial; +Cc: linux-serial



  Dear Developers.

There is a misprint in linux-2.6.0/drivers/serial/Kconfig file concerning 8250 driver

/drivers/serial/Kconfig states

   config SERIAL_8250
             ........................
   	     To compile this driver as a module, choose M here: the
 	     module will be called serial.

But in real world the module is called 8250 (but not serial). This misprint can lead to confusion. (user will not find desired module)

Best regards,
Grigory Rubtsov.


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

* (unknown)
@ 2003-12-18  7:37 achen1
  0 siblings, 0 replies; 76+ messages in thread
From: achen1 @ 2003-12-18  7:37 UTC (permalink / raw)




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

* (unknown), 
@ 2003-11-18 13:26 Michael Kohne
  0 siblings, 0 replies; 76+ messages in thread
From: Michael Kohne @ 2003-11-18 13:26 UTC (permalink / raw)
  To: linux-serial; +Cc: tytso

Proposed modification to the low_latency flag in version 5.05c of the
linux 16550 driver (drivers/char/serial.c).

My ultimate goal is to get this change accepted into the kernel so that I
don't have to maintain it on our end forever.

Background:
My company (Gasboy LLC) builds fuel management systems. Among other things
our systems talk via RS-422/485 lines to a variety of devices. Our newest
product is linux based and uses an 8 port serial board based on Exar 16654
quad uarts. A single serial port may be used to talk to up 32 devices on a
422 or 485 loop. The linux system is the master and polls the devices for
status information. When we poll a device, we send a small message out
including the device's address and expect the device to respond. If the
device does not respond in X milliseconds, we go on to the next. It is
important to minimize the timeout (X) so that we can talk to as many
devices as possible in as short a time as possible (the devices are gas
pumps, card readers, etc). Minimizing X becomes especially important when
devices are disabled or the system is mis-configured to talk to more
devices than exist (we don't want to hold up operations on live devices
waiting for dead ones). Timeouts are thus specified in terms of when the
FIRST character (STX) comes back from the device. If the STX is not
received in time, the device is assumed to be not present. The timeouts
are VERY short (on the order of 20-30 milliseconds).

The problem:
The old system hardware had uarts with no FIFO. Therefore, getting the STX
immediately after it hit the uart was no problem. The new system has 64
byte fifos. Since the linux serial drivers set the fifo to 56 bytes (a
good choice for high-bandwidth communications), the response packet (22
bytes) fits entirely in the fifo without hitting the trigger. The uart
will wait for 4 empty character times before it triggers the interrupt. At
9600 baud (about 1 millisecond per character) that's about 26 milliseconds
after the STX came in before the application sees it. Since the remote
device DOES take some time to respond, adding 26 milliseconds to the
response time causes our system to believe the device is gone and try to
recover appropriately.

Attempted solutions:
I have played with our timeouts, but significantly extending them (to the
point that they cover the fifo latency) causes user-visible delays when
large numbers of devices are configured on the loop, but missing.
I tried forcing the system to treat the relevant uarts as 16450 instead of
16654, but then we start dropping characters on a regular basis
(especially when heavy ethernet or ppp traffic occurs), thus slowing the
loops down again.
I do have the low_latency flag set, but that of course only changes how
data moves around AFTER it's received from the uart. It does nothing to
speed data in from the uart.

The proposed solution:
An optimal solution to the problem seems (to me) to be reducing the FIFO
trigger levels whenever low_latency is set on the port. This minimizes the
amount of time from when a character is received to when the application
layer sees it (which I believe to be the point of the low_latency flag
already).

Problems with this solution:
1) By reducing the receive fifo trigger level, we significantly increase
the interrupt rate of the uart, and therefore the overhead in servicing
it. I'm OK with this because the low_latency flag already specifies that
you are trading CPU overhead for latency.

2) Conflating the trigger level changes with the established behaviour of
low_latency seems appropriate to me, but better-informed persons might
well disagree. The alternative (to maintain a seperate flag) seems worse.



Results:
On a kernel with this patch installed, I did some timing analysis. My test
code sends a packet out a 422 port and waits for an STX to come back. With
setserial <port> ^low_latency, my timings are about 34 milliseconds. With
setserial <port> low_latency, my timings are 17 milliseconds. (The 34
milliseconds matches the times I got with my old kernel).


Addendum:
In the process of internally reviewing this patch at our company, I found
another division that had made a similar modification for internal use. So
I am now convinced that this is a useful modification.



The proposed patch (in diff -u format):
This patch is against the standard serial.c distributed with the 2.4.22
kernel.
If folks think that this is reasonable for kernel inclusion, I'll port it
to 2.5/2.6 as well.

--- serial.2.4.22.c	Tue Nov 11 02:13:41 2003
+++ serial.c	Tue Nov 11 02:13:04 2003
@@ -62,6 +62,9 @@
  *        Robert Schwebel <robert@schwebel.de>,
  *        Juergen Beisert <jbeisert@eurodsn.de>,
  *        Theodore Ts'o <tytso@mit.edu>
+ *
+ * 11/03: Set minimum fifo trigger level when low_latency set.
+ *        Michael Kohne <mhkohne@discordia.org>
  */

 static char *serial_version = "5.05c";
@@ -1728,7 +1731,10 @@

 	/* Set up FIFO's */
 	if (uart_config[info->state->type].flags & UART_USE_FIFO) {
-		if ((info->state->baud_base / quot) < 2400)
+		/* minimize lag time on low baud or user request */
+		/* otherwise, use appropriate default for this uart */
+		if ( ((info->state->baud_base / quot) < 2400) ||
+			(info->tty->low_latency) )
 			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
 #ifdef CONFIG_SERIAL_RSA
 		else if (info->state->type == PORT_RSA)




-- 
Michael Kohne        mhkohne@discordia.org
"You should be smarter than the equipment you are trying to operate." --
Matt Osborne



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

* (unknown)
@ 2002-08-27  1:48 Alex Pavloff
  0 siblings, 0 replies; 76+ messages in thread
From: Alex Pavloff @ 2002-08-27  1:48 UTC (permalink / raw)
  To: 'linux-serial@vger.kernel.org'


Good (morning/afternoon/evening) folks,

I am writing Modbus RTU code for Linux 2.4.19.  While seeminly simple to do
in userspace, there's one big kicker that I can't handle there easily.
Modbus RTU is a binary serial protocol used in industrial automation.  First
used by the Modicon PLCs, it's found on a variety of devices from a variety
of manufacturers.

The specification is at www.modbus.org, under "Modbus Standard Library", and
its the Modbus Serial Protocol Reference Guide.

Here's the part that I don't think I can resolve in userspace:
-----
RTU Framing
In RTU mode, messages start with a silent interval of at least 3.5 character
times. This is most easily implemented as a multiple of character times at
the baud rate that is being used on the network (shown as T1-T2-T3-T4 in the
figure below). The first field then transmitted is the device address.

The allowable characters transmitted for all fields are hexadecimal 0-9,
A-F. Networked devices monitor the network bus continuously, including
during the 'silent' intervals. When the first field (the address field) is
received, each device decodes it to find out if it is the addressed device.

Following the last transmitted character, a similar interval of at least 3.5
character times marks the end of the message. A new message can begin after
this interval.

The entire message frame must be transmitted as a continuous stream. If a
silent interval of more than 1.5 character times occurs before completion of
the frame, the receiving device flushes the incomplete message and assumes
that the next byte will be the address field of a new message.
-----

3.5 character times at high baud rates is not something I can pull off with
termios.  To get the Modbus RTU frames without resorting to some really
strange code in userspace, should I write a line-discipline module whose
sole purpose is to deal with the character timing?

Any comments (yay/nay/huh?) appreciated.

Alex Pavloff
Software Engineer
Eason Technology
 



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

end of thread, other threads:[~2014-11-02 20:01 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-09 17:49 (unknown), Sebastian Andrzej Siewior
2014-07-09 17:49 ` [PATCH 1/6] tty: serial: 8250 core: provide a function to export uart_8250_port Sebastian Andrzej Siewior
2014-07-10 14:30   ` Olivier Galibert
2014-07-16  8:22     ` Sebastian Andrzej Siewior
2014-07-09 17:49 ` [PATCH 2/6] tty: serial: 8250 core: allow to overwrite & export serial8250_startup() Sebastian Andrzej Siewior
2014-07-10 14:54   ` One Thousand Gnomes
2014-07-10 14:55   ` Sebastian Andrzej Siewior
2014-07-09 17:49 ` [PATCH 3/6] tty: serial: 8250 core: add runtime pm Sebastian Andrzej Siewior
2014-07-10  6:28   ` Tony Lindgren
2014-07-16  8:26     ` Sebastian Andrzej Siewior
2014-07-21 13:34   ` Mika Westerberg
2014-07-09 17:49 ` [PATCH 4/6] tty: serial: 8250-core: reorder serial8250_stop_rx() & serial8250_start_tx() Sebastian Andrzej Siewior
2014-07-09 17:49 ` [PATCH 5/6] tty: serial: 8250-core: add rs485 support Sebastian Andrzej Siewior
2014-07-09 19:01   ` Lennart Sorensen
2014-07-10 15:55     ` Sebastian Andrzej Siewior
2014-07-10 14:52   ` One Thousand Gnomes
2014-07-09 17:49 ` [PATCH 6/6] tty: serial: Add 8250-core based omap driver Sebastian Andrzej Siewior
2014-07-10  7:09   ` Tony Lindgren
2014-07-10 15:47     ` Sebastian Andrzej Siewior
2014-07-10 16:03       ` Carlos Hernandez
2014-07-10 16:14         ` menon.nishanth
2014-07-11  6:41       ` Tony Lindgren
2014-07-16 12:11         ` Sebastian Andrzej Siewior
2014-07-16 12:32           ` Tony Lindgren
2014-07-16 13:00             ` Sekhar Nori
2014-08-08 11:05   ` Heikki Krogerus
2014-07-09 17:58 ` [RFC v3] 8250-core based serial driver for OMAP Sebastian Andrzej Siewior
     [not found] <1570038211.167595.1414613146892.JavaMail.yahoo@jws10056.mail.ne1.yahoo.com>
     [not found] ` <1835234304.171617.1414613165674.JavaMail.yahoo@jws10089.mail.ne1.yahoo.com>
     [not found]   ` <1938862685.172387.1414613200459.JavaMail.yahoo@jws100180.mail.ne1.yahoo.com>
     [not found]     ` <705402329.170339.1414613213653.JavaMail.yahoo@jws10087.mail.ne1.yahoo.com>
     [not found]       ` <760168749.169371.1414613227586.JavaMail.yahoo@jws10082.mail.ne1.yahoo.com>
     [not found]         ` <1233923671.167957.1414613439879.JavaMail.yahoo@jws10091.mail.ne1.yahoo.com>
     [not found]           ` <925985882.172122.1414613520734.JavaMail.yahoo@jws100207.mail.ne1.yahoo.com>
     [not found]             ` <1216694778.172990.1414613570775.JavaMail.yahoo@jws100152.mail.ne1.yahoo.com>
     [not found]               ` <1213035306.169838.1414613612716.JavaMail.yahoo@jws10097.mail.ne1.yahoo.com>
     [not found]                 ` <2058591563.172973.1414613668636.JavaMail.yahoo@jws10089.mail.ne1.yahoo.com>
     [not found]                   ` <1202030640.175493 .1414613712352.JavaMail.yahoo@jws10036.mail.ne1.yahoo.com>
     [not found]                     ` <1111049042.175610.1414613739099.JavaMail.yahoo@jws100165.mail.ne1.yahoo.com>
     [not found]                       ` <574125160.175950.1414613784216.JavaMail.yahoo@jws100158.mail.ne1.yahoo.com>
     [not found]                         ` <1726966600.175552.1414613846198.JavaMail.yahoo@jws100190.mail.ne1.yahoo.com>
     [not found]                           ` <976499752.219775.1414613888129.JavaMail.yahoo@jws100101.mail.ne1.yahoo.com>
     [not found]                             ` <1400960529.171566.1414613936238.JavaMail.yahoo@jws10059.mail.ne1.yahoo.com>
     [not found]                               ` <1333619289.175040.1414613999304.JavaMail.yahoo@jws100196.mail.ne1.yahoo.com>
     [not found]                                 ` <1038759122.176173.1414614054070.JavaMail.yahoo@jws100138.mail.ne1.yahoo.com>
     [not found]                                   ` <1109995533.176150.1414614101940.JavaMail.yahoo@jws100140.mail.ne1.yahoo.com>
     [not found]                                     ` <809474730.174920.1414614143971.JavaMail.yahoo@jws100154.mail.ne1.yahoo.com>
     [not found]                                       ` <1234226428.170349.1414614189490.JavaMail .yahoo@jws10056.mail.ne1.yahoo.com>
     [not found]                                         ` <1122464611.177103.1414614228916.JavaMail.yahoo@jws100161.mail.ne1.yahoo.com>
     [not found]                                           ` <1350859260.174219.1414614279095.JavaMail.yahoo@jws100176.mail.ne1.yahoo.com>
     [not found]                                             ` <1730751880.171557.1414614322033.JavaMail.yahoo@jws10060.mail.ne1.yahoo.com>
     [not found]                                               ` <642429550.177328.1414614367628.JavaMail.yahoo@jws100165.mail.ne1.yahoo.com>
     [not found]                                                 ` <1400780243.20511.1414614418178.JavaMail.yahoo@jws100162.mail.ne1.yahoo.com>
     [not found]                                                   ` <2025652090.173204.1414614462119.JavaMail.yahoo@jws10087.mail.ne1.yahoo.com>
     [not found]                                                     ` <859211720.180077.1414614521867.JavaMail.yahoo@jws100147.mail.ne1.yahoo.com>
     [not found]                                                       ` <258705675.173585.1414614563057.JavaMail.yahoo@jws10078.mail.ne1.yahoo.com>
     [not found]                                                         ` <1773234186.173687.1414614613736.JavaMail.yahoo@jws10078.mail.ne1.yahoo.com>
     [not found]                                                           ` <1132079010.173033.1414614645153.JavaMail.yahoo@jws10066.mail.ne1.ya hoo.com>
     [not found]                                                             ` <1972302405.176488.1414614708676.JavaMail.yahoo@jws100166.mail.ne1.yahoo.com>
     [not found]                                                               ` <1713123000.176308.1414614771694.JavaMail.yahoo@jws10045.mail.ne1.yahoo.com>
     [not found]                                                                 ` <299800233.173413.1414614817575.JavaMail.yahoo@jws10066.mail.ne1.yahoo.com>
     [not found]                                                                   ` <494469968.179875.1414614903152.JavaMail.yahoo@jws100144.mail.ne1.yahoo.com>
     [not found]                                                                     ` <2136945987.171995.1414614942776.JavaMail.yahoo@jws10091.mail.ne1.yahoo.com>
     [not found]                                                                       ` <257674219.177708.1414615022592.JavaMail.yahoo@jws100181.mail.ne1.yahoo.com>
     [not found]                                                                         ` <716927833.181664.1414615075308.JavaMail.yahoo@jws100145.mail.ne1.yahoo.com>
     [not found]                                                                           ` <874940984.178797.1414615132802.JavaMail.yahoo@jws100157.mail.ne1.yahoo.com>
     [not found]                                                                             ` <1283488887.176736.1414615187657.JavaMail.yahoo@jws100183.mail.ne1.yahoo.com>
     [not found]                                                                               ` <777665713.175887.1414615236293.JavaMail.yahoo@jws10083.mail.ne1.yahoo.com>
     [not found]                                                                                 ` <585395776.176325.1 414615298260.JavaMail.yahoo@jws10033.mail.ne1.yahoo.com>
     [not found]                                                                                   ` <178352191.221832.1414615355071.JavaMail.yahoo@jws100104.mail.ne1.yahoo.com>
     [not found]                                                                                     ` <108454213.176606.1414615522058.JavaMail.yahoo@jws10053.mail.ne1.yahoo.com>
     [not found]                                                                                       ` <1617229176.177502.1414615563724.JavaMail.yahoo@jws10030.mail.ne1.yahoo.com>
     [not found]                                                                                         ` <324334617.178254.1414615625247.JavaMail.yahoo@jws10089.mail.ne1.yahoo.com>
     [not found]                                                                                           ` <567135865.82376.1414615664442.JavaMail.yahoo@jws100136.mail.ne1.yahoo.com>
     [not found]                                                                                             ` <764758300.179669.1414615711821.JavaMail.yahoo@jws100107.mail.ne1.yahoo.com>
     [not found]                                                                                               ` <1072855470.183388.1414615775798.JavaMail.yahoo@jws100147.mail.ne1.yahoo.com>
     [not found]                                                                                                 ` <2134283632.173314.1414615831322.JavaMail.yahoo@jws10094.mail.ne1.yahoo.com>
     [not found]                                                                                                   ` <1454491902.178612.1414615875076.JavaMail.yahoo@jws100209.mail.ne1.yahoo.com>
     [not found]                                                                                                     ` <1881200547.147301.1414958000634.JavaMail.yahoo@jws100209.mail.ne1.yahoo.com>
2014-11-02 19:54                                                                                                       ` (unknown) MRS GRACE MANDA
  -- strict thread matches above, loose matches on Subject: below --
2013-07-31  6:26 (unknown), Yoshinori Otani
2012-11-12 13:21 (unknown), Jayne Montgomery
2012-11-12 12:49 (unknown), Jayne Montgomery
2012-11-12 10:52 (unknown), Jayne Montgomery
2012-04-12 11:21 (unknown), monicaaluke01@gmail.com
2012-03-04 17:59 (unknown), Matthieu CASTET
2012-02-25 14:29 (unknown), Grieger, Anne
2011-11-18  4:54 (unknown), Robbin Setzer
2011-10-09 20:56 (unknown), MONEY GRAM CUSTOMER CARE
2011-04-14  7:15 (unknown) pradeep Annavarapu
2011-03-03  5:39 (unknown) pradeep Annavarapu
2011-03-01 23:48 (unknown), Mr. henry
2011-03-01 23:47 (unknown), Mr. henry
2010-11-19  4:38 (unknown) Mayank Rana
2007-11-25  2:10 (unknown) Thomas Bogendoerfer
2007-04-30 22:06 (unknown) Corey Minyard
     [not found] <000601c7708e$f36a37c0$0200a8c0@7950gx2>
2007-03-27 16:42 ` (unknown), Chris Mawer
2006-10-15 14:20 (unknown) upcajxhkb
2006-08-07  2:46 (unknown), colet aeneas
2006-06-16 17:54 (unknown) kueth
2006-05-01  7:56 (unknown) bec
2006-04-30 23:40 (unknown) jungjackson
2006-03-11 21:02 (unknown) lwvxfb
2005-11-17 18:48 (unknown) Stuart MacDonald
2005-07-27 16:19 (unknown) drlim
2005-07-23  4:50 (unknown) Mr.Derrick Tanner.
2005-06-21 11:48 (unknown) pliskie
2005-06-16 12:14 (unknown) LeslieGolden
2005-06-11  2:00 (unknown) dtasman
2005-06-10  2:30 (unknown) bewails
2005-05-16  8:11 (unknown) ucmjfspdc
2005-05-08  3:52 (unknown) xiytw
2005-04-22  2:00 (unknown) vyidqsw
2004-10-09 22:23 (unknown) zzz
2004-09-02 14:27 (unknown), Larry
2004-08-24  6:05 (unknown) Francisco M. Marzoa Alonso
2004-08-14  6:38 (unknown) sky
2004-08-11  1:10 (unknown) sky
2004-08-07  4:32 (unknown) sky
2004-08-07  1:05 (unknown) kkkkkkk
2004-08-06  1:02 (unknown) lowinterrest
2004-08-01 10:30 (unknown) sky
2004-03-16 22:48 (unknown), Kumar Gala
2004-03-15 22:13 (unknown), Brice Blount
2003-12-21 13:39 (unknown) "Grigorii Rubtsov" 
2003-12-18  7:37 (unknown) achen1
2003-11-18 13:26 (unknown), Michael Kohne
2002-08-27  1:48 (unknown) Alex Pavloff

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).