From: Petr Štetiar Date: Fri, 13 Jan 2017 10:42:08 +0000 (+0100) Subject: imx6: kernel: Backport serial port fixes X-Git-Tag: v17.01.0-rc1~70 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=26e4fee6e28d5f5d50a5ce74aa044fa5b3a9db65;p=oweals%2Fopenwrt.git imx6: kernel: Backport serial port fixes Signed-off-by: Petr Štetiar --- 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 index 0000000000..0a117f668f --- /dev/null +++ b/target/linux/imx6/patches-4.4/110-serial-imx-repair-and-complete-handshaking.patch @@ -0,0 +1,78 @@ +From 90ebc4838666d148eac5bbac6f4044e5b25cd2d6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +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 +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Petr Å tetiar +--- + 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 index 0000000000..a06557542a --- /dev/null +++ b/target/linux/imx6/patches-4.4/111-serial-imx-fix-polarity-of-RI.patch @@ -0,0 +1,38 @@ +From 9a061cea4477f26a1dfcc0a08dc20575016e91df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +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 +Signed-off-by: Petr Å tetiar +--- + 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 index 0000000000..0b803b7bda --- /dev/null +++ b/target/linux/imx6/patches-4.4/112-serial-imx-let-irq-handler-return-IRQ_NONE-if-no-eve.patch @@ -0,0 +1,72 @@ +From de4356da2cd1a1857513047997d81143cb95a4e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +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 +Signed-off-by: Petr Å tetiar +--- + 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 index 0000000000..8978d33e6e --- /dev/null +++ b/target/linux/imx6/patches-4.4/113-serial-imx-make-sure-unhandled-irqs-are-disabled.patch @@ -0,0 +1,61 @@ +From a58c6360b9eb3a2374b0b069ba9ce7baec0f26df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +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 +Signed-off-by: Petr Å tetiar +--- + 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 +