imx6: kernel: Backport serial port fixes
authorPetr Štetiar <ynezz@true.cz>
Fri, 13 Jan 2017 10:42:08 +0000 (11:42 +0100)
committerJohn Crispin <john@phrozen.org>
Sun, 15 Jan 2017 16:41:14 +0000 (17:41 +0100)
Signed-off-by: Petr Štetiar <ynezz@true.cz>
target/linux/imx6/patches-4.4/110-serial-imx-repair-and-complete-handshaking.patch [new file with mode: 0644]
target/linux/imx6/patches-4.4/111-serial-imx-fix-polarity-of-RI.patch [new file with mode: 0644]
target/linux/imx6/patches-4.4/112-serial-imx-let-irq-handler-return-IRQ_NONE-if-no-eve.patch [new file with mode: 0644]
target/linux/imx6/patches-4.4/113-serial-imx-make-sure-unhandled-irqs-are-disabled.patch [new file with mode: 0644]

diff --git a/target/linux/imx6/patches-4.4/110-serial-imx-repair-and-complete-handshaking.patch b/target/linux/imx6/patches-4.4/110-serial-imx-repair-and-complete-handshaking.patch
new file mode 100644 (file)
index 0000000..0a117f6
--- /dev/null
@@ -0,0 +1,78 @@
+From 90ebc4838666d148eac5bbac6f4044e5b25cd2d6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Sun, 18 Oct 2015 21:34:46 +0200
+Subject: [PATCH] serial: imx: repair and complete handshaking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The .get_mctrl callback should not report the status of RTS or LOOP, so
+drop this. Instead implement reporting the state of CAR (aka DCD) and
+RI.
+
+For .set_mctrl implement setting the DTR line.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/tty/serial/imx.c | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
+index 76818f5..086675e 100644
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -148,8 +148,11 @@
+ #define USR2_TXFE      (1<<14) /* Transmit buffer FIFO empty */
+ #define USR2_DTRF      (1<<13) /* DTR edge interrupt flag */
+ #define USR2_IDLE      (1<<12) /* Idle condition */
++#define USR2_RIDELT    (1<<10) /* Ring Interrupt Delta */
++#define USR2_RIIN      (1<<9)  /* Ring Indicator Input */
+ #define USR2_IRINT     (1<<8)  /* Serial infrared interrupt flag */
+ #define USR2_WAKE      (1<<7)  /* Wake */
++#define USR2_DCDIN     (1<<5)  /* Data Carrier Detect Input */
+ #define USR2_RTSF      (1<<4)  /* RTS edge interrupt flag */
+ #define USR2_TXDC      (1<<3)  /* Transmitter complete */
+ #define USR2_BRCD      (1<<2)  /* Break condition */
+@@ -804,16 +807,19 @@ static unsigned int imx_tx_empty(struct uart_port *port)
+ static unsigned int imx_get_mctrl(struct uart_port *port)
+ {
+       struct imx_port *sport = (struct imx_port *)port;
+-      unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
++      unsigned int tmp = TIOCM_DSR;
++      unsigned usr1 = readl(sport->port.membase + USR1);
+-      if (readl(sport->port.membase + USR1) & USR1_RTSS)
++      if (usr1 & USR1_RTSS)
+               tmp |= TIOCM_CTS;
+-      if (readl(sport->port.membase + UCR2) & UCR2_CTS)
+-              tmp |= TIOCM_RTS;
++      /* in DCE mode DCDIN is always 0 */
++      if (!(usr1 & USR2_DCDIN))
++              tmp |= TIOCM_CAR;
+-      if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP)
+-              tmp |= TIOCM_LOOP;
++      /* in DCE mode RIIN is always 0 */
++      if (readl(sport->port.membase + USR2) & USR2_RIIN)
++              tmp |= TIOCM_RI;
+       return tmp;
+ }
+@@ -831,6 +837,11 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+               writel(temp, sport->port.membase + UCR2);
+       }
++      temp = readl(sport->port.membase + UCR3) & ~UCR3_DSR;
++      if (!(mctrl & TIOCM_DTR))
++              temp |= UCR3_DSR;
++      writel(temp, sport->port.membase + UCR3);
++
+       temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
+       if (mctrl & TIOCM_LOOP)
+               temp |= UTS_LOOP;
+-- 
+1.9.1
+
diff --git a/target/linux/imx6/patches-4.4/111-serial-imx-fix-polarity-of-RI.patch b/target/linux/imx6/patches-4.4/111-serial-imx-fix-polarity-of-RI.patch
new file mode 100644 (file)
index 0000000..a065575
--- /dev/null
@@ -0,0 +1,38 @@
+From 9a061cea4477f26a1dfcc0a08dc20575016e91df Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Thu, 24 Mar 2016 14:24:20 +0100
+Subject: [PATCH 1/3] serial: imx: fix polarity of RI
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When in DTE mode, the bit USR2_RIIN is active low. So invert the logic
+accordingly.
+
+Fixes: 90ebc4838666 ("serial: imx: repair and complete handshaking")
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/tty/serial/imx.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
+index 231e7d5..bfc4555 100644
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -797,9 +797,9 @@ static unsigned int imx_get_hwmctrl(struct imx_port *sport)
+       if (!(usr1 & USR2_DCDIN))
+               tmp |= TIOCM_CAR;
+-      /* in DCE mode RIIN is always 0 */
+-      if (readl(sport->port.membase + USR2) & USR2_RIIN)
+-              tmp |= TIOCM_RI;
++      if (sport->dte_mode)
++              if (!(readl(sport->port.membase + USR2) & USR2_RIIN))
++                      tmp |= TIOCM_RI;
+       return tmp;
+ }
+-- 
+1.9.1
+
diff --git a/target/linux/imx6/patches-4.4/112-serial-imx-let-irq-handler-return-IRQ_NONE-if-no-eve.patch b/target/linux/imx6/patches-4.4/112-serial-imx-let-irq-handler-return-IRQ_NONE-if-no-eve.patch
new file mode 100644 (file)
index 0000000..0b803b7
--- /dev/null
@@ -0,0 +1,72 @@
+From de4356da2cd1a1857513047997d81143cb95a4e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Thu, 24 Mar 2016 14:24:21 +0100
+Subject: [PATCH 2/3] serial: imx: let irq handler return IRQ_NONE if no event
+ was handled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This gives the irq core a chance to disable the serial interrupt in case
+an event isn't cleared in the handler.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/tty/serial/imx.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
+index bfc4555..5ced61e 100644
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -734,6 +734,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
+       struct imx_port *sport = dev_id;
+       unsigned int sts;
+       unsigned int sts2;
++      irqreturn_t ret = IRQ_NONE;
+       sts = readl(sport->port.membase + USR1);
+       sts2 = readl(sport->port.membase + USR2);
+@@ -743,26 +744,34 @@ static irqreturn_t imx_int(int irq, void *dev_id)
+                       imx_dma_rxint(sport);
+               else
+                       imx_rxint(irq, dev_id);
++              ret = IRQ_HANDLED;
+       }
+       if ((sts & USR1_TRDY &&
+            readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
+           (sts2 & USR2_TXDC &&
+-           readl(sport->port.membase + UCR4) & UCR4_TCEN))
++           readl(sport->port.membase + UCR4) & UCR4_TCEN)) {
+               imx_txint(irq, dev_id);
++              ret = IRQ_HANDLED;
++      }
+-      if (sts & USR1_RTSD)
++      if (sts & USR1_RTSD) {
+               imx_rtsint(irq, dev_id);
++              ret = IRQ_HANDLED;
++      }
+-      if (sts & USR1_AWAKE)
++      if (sts & USR1_AWAKE) {
+               writel(USR1_AWAKE, sport->port.membase + USR1);
++              ret = IRQ_HANDLED;
++      }
+       if (sts2 & USR2_ORE) {
+               sport->port.icount.overrun++;
+               writel(USR2_ORE, sport->port.membase + USR2);
++              ret = IRQ_HANDLED;
+       }
+-      return IRQ_HANDLED;
++      return ret;
+ }
+ /*
+-- 
+1.9.1
+
diff --git a/target/linux/imx6/patches-4.4/113-serial-imx-make-sure-unhandled-irqs-are-disabled.patch b/target/linux/imx6/patches-4.4/113-serial-imx-make-sure-unhandled-irqs-are-disabled.patch
new file mode 100644 (file)
index 0000000..8978d33
--- /dev/null
@@ -0,0 +1,61 @@
+From a58c6360b9eb3a2374b0b069ba9ce7baec0f26df Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Thu, 24 Mar 2016 14:24:22 +0100
+Subject: [PATCH 3/3] serial: imx: make sure unhandled irqs are disabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Make sure that events that are not handled in the irq function don't
+trigger an interrupt.
+
+When the serial port is operated in DTE mode, the events for DCD and RI
+events are enabled after a system reset by default.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/tty/serial/imx.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
+index 5ced61e..fcd48fd 100644
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -1221,11 +1221,32 @@ static int imx_startup(struct uart_port *port)
+       temp |= (UCR2_RXEN | UCR2_TXEN);
+       if (!sport->have_rtscts)
+               temp |= UCR2_IRTS;
++      /*
++       * make sure the edge sensitive RTS-irq is disabled,
++       * we're using RTSD instead.
++       */
++      if (!is_imx1_uart(sport))
++              temp &= ~UCR2_RTSEN;
+       writel(temp, sport->port.membase + UCR2);
+       if (!is_imx1_uart(sport)) {
+               temp = readl(sport->port.membase + UCR3);
+-              temp |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP;
++
++              /*
++               * The effect of RI and DCD differs depending on the UFCR_DCEDTE
++               * bit. In DCE mode they control the outputs, in DTE mode they
++               * enable the respective irqs. At least the DCD irq cannot be
++               * cleared on i.MX25 at least, so it's not usable and must be
++               * disabled. I don't have test hardware to check if RI has the
++               * same problem but I consider this likely so it's disabled for
++               * now, too.
++               */
++              temp |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP |
++                      UCR3_RI | UCR3_DCD;
++
++              if (sport->dte_mode)
++                      temp &= ~(UCR3_RI | UCR3_DCD);
++
+               writel(temp, sport->port.membase + UCR3);
+       }
+-- 
+1.9.1
+