Update Linux to v5.10.109
Sourced from [1]
[1] https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.109.tar.xz
Change-Id: I19bca9fc6762d4e63bcf3e4cba88bbe560d9c76c
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e5ed4ab..93cd8ad 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -8,10 +8,6 @@
* Copyright (C) 2004 Pengutronix
*/
-#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
@@ -24,6 +20,7 @@
#include <linux/serial.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/ktime.h>
#include <linux/pinctrl/consumer.h>
#include <linux/rational.h>
#include <linux/slab.h>
@@ -192,6 +189,13 @@
enum imx_uart_type devtype;
};
+enum imx_tx_state {
+ OFF,
+ WAIT_AFTER_RTS,
+ SEND,
+ WAIT_AFTER_SEND,
+};
+
struct imx_port {
struct uart_port port;
struct timer_list timer;
@@ -199,6 +203,8 @@
unsigned int have_rtscts:1;
unsigned int have_rtsgpio:1;
unsigned int dte_mode:1;
+ unsigned int inverted_tx:1;
+ unsigned int inverted_rx:1;
struct clk *clk_ipg;
struct clk *clk_per;
const struct imx_uart_data *devdata;
@@ -226,6 +232,10 @@
unsigned int dma_tx_nents;
unsigned int saved_reg[10];
bool context_saved;
+
+ enum imx_tx_state tx_state;
+ struct hrtimer trigger_start_tx;
+ struct hrtimer trigger_stop_tx;
};
struct imx_port_ucrs {
@@ -363,7 +373,7 @@
/*
* Save and restore functions for UCR1, UCR2 and UCR3 registers
*/
-#if defined(CONFIG_SERIAL_IMX_CONSOLE)
+#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_ucrs_save(struct imx_port *sport,
struct imx_port_ucrs *ucr)
{
@@ -402,6 +412,15 @@
mctrl_gpio_set(sport->gpios, sport->port.mctrl);
}
+static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
+{
+ long sec = msec / MSEC_PER_SEC;
+ long nsec = (msec % MSEC_PER_SEC) * 1000000;
+ ktime_t t = ktime_set(sec, nsec);
+
+ hrtimer_start(hrt, t, HRTIMER_MODE_REL);
+}
+
/* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port)
{
@@ -429,7 +448,10 @@
static void imx_uart_stop_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
- u32 ucr1;
+ u32 ucr1, ucr4, usr2;
+
+ if (sport->tx_state == OFF)
+ return;
/*
* We are maybe in the SMP context, so if the DMA TX thread is running
@@ -441,21 +463,44 @@
ucr1 = imx_uart_readl(sport, UCR1);
imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1);
- /* in rs485 mode disable transmitter if shifter is empty */
- if (port->rs485.flags & SER_RS485_ENABLED &&
- imx_uart_readl(sport, USR2) & USR2_TXDC) {
- u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4;
- if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
- imx_uart_rts_active(sport, &ucr2);
- else
- imx_uart_rts_inactive(sport, &ucr2);
- imx_uart_writel(sport, ucr2, UCR2);
+ usr2 = imx_uart_readl(sport, USR2);
+ if (!(usr2 & USR2_TXDC)) {
+ /* The shifter is still busy, so retry once TC triggers */
+ return;
+ }
- imx_uart_start_rx(port);
+ ucr4 = imx_uart_readl(sport, UCR4);
+ ucr4 &= ~UCR4_TCEN;
+ imx_uart_writel(sport, ucr4, UCR4);
- ucr4 = imx_uart_readl(sport, UCR4);
- ucr4 &= ~UCR4_TCEN;
- imx_uart_writel(sport, ucr4, UCR4);
+ /* in rs485 mode disable transmitter */
+ if (port->rs485.flags & SER_RS485_ENABLED) {
+ if (sport->tx_state == SEND) {
+ sport->tx_state = WAIT_AFTER_SEND;
+ start_hrtimer_ms(&sport->trigger_stop_tx,
+ port->rs485.delay_rts_after_send);
+ return;
+ }
+
+ if (sport->tx_state == WAIT_AFTER_RTS ||
+ sport->tx_state == WAIT_AFTER_SEND) {
+ u32 ucr2;
+
+ hrtimer_try_to_cancel(&sport->trigger_start_tx);
+
+ ucr2 = imx_uart_readl(sport, UCR2);
+ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+ imx_uart_rts_active(sport, &ucr2);
+ else
+ imx_uart_rts_inactive(sport, &ucr2);
+ imx_uart_writel(sport, ucr2, UCR2);
+
+ imx_uart_start_rx(port);
+
+ sport->tx_state = OFF;
+ }
+ } else {
+ sport->tx_state = OFF;
}
}
@@ -463,18 +508,21 @@
static void imx_uart_stop_rx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
- u32 ucr1, ucr2;
+ u32 ucr1, ucr2, ucr4;
ucr1 = imx_uart_readl(sport, UCR1);
ucr2 = imx_uart_readl(sport, UCR2);
+ ucr4 = imx_uart_readl(sport, UCR4);
if (sport->dma_is_enabled) {
ucr1 &= ~(UCR1_RXDMAEN | UCR1_ATDMAEN);
} else {
ucr1 &= ~UCR1_RRDYEN;
ucr2 &= ~UCR2_ATEN;
+ ucr4 &= ~UCR4_OREN;
}
imx_uart_writel(sport, ucr1, UCR1);
+ imx_uart_writel(sport, ucr4, UCR4);
ucr2 &= ~UCR2_RXEN;
imx_uart_writel(sport, ucr2, UCR2);
@@ -653,28 +701,50 @@
if (!sport->port.x_char && uart_circ_empty(&port->state->xmit))
return;
+ /*
+ * We cannot simply do nothing here if sport->tx_state == SEND already
+ * because UCR1_TXMPTYEN might already have been cleared in
+ * imx_uart_stop_tx(), but tx_state is still SEND.
+ */
+
if (port->rs485.flags & SER_RS485_ENABLED) {
- u32 ucr2;
+ if (sport->tx_state == OFF) {
+ u32 ucr2 = imx_uart_readl(sport, UCR2);
+ if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
+ imx_uart_rts_active(sport, &ucr2);
+ else
+ imx_uart_rts_inactive(sport, &ucr2);
+ imx_uart_writel(sport, ucr2, UCR2);
- ucr2 = imx_uart_readl(sport, UCR2);
- if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
- imx_uart_rts_active(sport, &ucr2);
- else
- imx_uart_rts_inactive(sport, &ucr2);
- imx_uart_writel(sport, ucr2, UCR2);
+ if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
+ imx_uart_stop_rx(port);
- if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
- imx_uart_stop_rx(port);
-
- /*
- * Enable transmitter and shifter empty irq only if DMA is off.
- * In the DMA case this is done in the tx-callback.
- */
- if (!sport->dma_is_enabled) {
- u32 ucr4 = imx_uart_readl(sport, UCR4);
- ucr4 |= UCR4_TCEN;
- imx_uart_writel(sport, ucr4, UCR4);
+ sport->tx_state = WAIT_AFTER_RTS;
+ start_hrtimer_ms(&sport->trigger_start_tx,
+ port->rs485.delay_rts_before_send);
+ return;
}
+
+ if (sport->tx_state == WAIT_AFTER_SEND
+ || sport->tx_state == WAIT_AFTER_RTS) {
+
+ hrtimer_try_to_cancel(&sport->trigger_stop_tx);
+
+ /*
+ * Enable transmitter and shifter empty irq only if DMA
+ * is off. In the DMA case this is done in the
+ * tx-callback.
+ */
+ if (!sport->dma_is_enabled) {
+ u32 ucr4 = imx_uart_readl(sport, UCR4);
+ ucr4 |= UCR4_TCEN;
+ imx_uart_writel(sport, ucr4, UCR4);
+ }
+
+ sport->tx_state = SEND;
+ }
+ } else {
+ sport->tx_state = SEND;
}
if (!sport->dma_is_enabled) {
@@ -788,9 +858,7 @@
if (rx & URXD_OVRRUN)
flg = TTY_OVERRUN;
-#ifdef SUPPORT_SYSRQ
sport->port.sysrq = 0;
-#endif
}
if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
@@ -919,6 +987,8 @@
usr2 &= ~USR2_ORE;
if (usr1 & (USR1_RRDY | USR1_AGTIM)) {
+ imx_uart_writel(sport, USR1_AGTIM, USR1);
+
__imx_uart_rxint(irq, dev_id);
ret = IRQ_HANDLED;
}
@@ -1065,8 +1135,6 @@
}
}
-#define RX_BUF_SIZE (PAGE_SIZE)
-
/*
* There are two kinds of RX DMA interrupts(such as in the MX6Q):
* [1] the RX DMA buffer is full.
@@ -1149,7 +1217,8 @@
}
/* RX DMA buffer periods */
-#define RX_DMA_PERIODS 4
+#define RX_DMA_PERIODS 16
+#define RX_BUF_SIZE (RX_DMA_PERIODS * PAGE_SIZE / 4)
static int imx_uart_start_rx_dma(struct imx_port *sport)
{
@@ -1348,7 +1417,7 @@
int retval, i;
unsigned long flags;
int dma_is_inited = 0;
- u32 ucr1, ucr2, ucr4;
+ u32 ucr1, ucr2, ucr3, ucr4;
retval = clk_prepare_enable(sport->clk_per);
if (retval)
@@ -1400,11 +1469,29 @@
imx_uart_writel(sport, ucr1, UCR1);
- ucr4 = imx_uart_readl(sport, UCR4) & ~UCR4_OREN;
+ ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR);
if (!sport->dma_is_enabled)
ucr4 |= UCR4_OREN;
+ if (sport->inverted_rx)
+ ucr4 |= UCR4_INVR;
imx_uart_writel(sport, ucr4, UCR4);
+ ucr3 = imx_uart_readl(sport, UCR3) & ~UCR3_INVT;
+ /*
+ * configure tx polarity before enabling tx
+ */
+ if (sport->inverted_tx)
+ ucr3 |= UCR3_INVT;
+
+ if (!imx_uart_is_imx1(sport)) {
+ ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
+
+ if (sport->dte_mode)
+ /* disable broken interrupts */
+ ucr3 &= ~(UCR3_RI | UCR3_DCD);
+ }
+ imx_uart_writel(sport, ucr3, UCR3);
+
ucr2 = imx_uart_readl(sport, UCR2) & ~UCR2_ATEN;
ucr2 |= (UCR2_RXEN | UCR2_TXEN);
if (!sport->have_rtscts)
@@ -1417,20 +1504,6 @@
ucr2 &= ~UCR2_RTSEN;
imx_uart_writel(sport, ucr2, UCR2);
- if (!imx_uart_is_imx1(sport)) {
- u32 ucr3;
-
- ucr3 = imx_uart_readl(sport, UCR3);
-
- ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
-
- if (sport->dte_mode)
- /* disable broken interrupts */
- ucr3 &= ~(UCR3_RI | UCR3_DCD);
-
- imx_uart_writel(sport, ucr3, UCR3);
- }
-
/*
* Enable modem status interrupts
*/
@@ -1488,10 +1561,6 @@
ucr2 = imx_uart_readl(sport, UCR2);
ucr2 &= ~(UCR2_TXEN | UCR2_ATEN);
imx_uart_writel(sport, ucr2, UCR2);
-
- ucr4 = imx_uart_readl(sport, UCR4);
- ucr4 &= ~UCR4_OREN;
- imx_uart_writel(sport, ucr4, UCR4);
spin_unlock_irqrestore(&sport->port.lock, flags);
/*
@@ -1504,10 +1573,15 @@
*/
spin_lock_irqsave(&sport->port.lock, flags);
+
ucr1 = imx_uart_readl(sport, UCR1);
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN);
-
imx_uart_writel(sport, ucr1, UCR1);
+
+ ucr4 = imx_uart_readl(sport, UCR4);
+ ucr4 &= ~UCR4_TCEN;
+ imx_uart_writel(sport, ucr4, UCR4);
+
spin_unlock_irqrestore(&sport->port.lock, flags);
clk_disable_unprepare(sport->clk_per);
@@ -1635,7 +1709,6 @@
if (termios->c_cflag & CRTSCTS)
ucr2 &= ~UCR2_IRTS;
-
if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) {
@@ -1862,10 +1935,6 @@
struct imx_port *sport = (struct imx_port *)port;
u32 ucr2;
- /* unimplemented */
- rs485conf->delay_rts_before_send = 0;
- rs485conf->delay_rts_after_send = 0;
-
/* RTS is required to control the transmitter */
if (!sport->have_rtscts && !sport->have_rtsgpio)
rs485conf->flags &= ~SER_RS485_ENABLED;
@@ -1920,7 +1989,7 @@
static struct imx_port *imx_uart_ports[UART_NR];
-#ifdef CONFIG_SERIAL_IMX_CONSOLE
+#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_console_putchar(struct uart_port *port, int ch)
{
struct imx_port *sport = (struct imx_port *)port;
@@ -1983,7 +2052,7 @@
* If the port was already initialised (eg, by a boot loader),
* try to determine the current setup.
*/
-static void __init
+static void
imx_uart_console_get_options(struct imx_port *sport, int *baud,
int *parity, int *bits)
{
@@ -2042,7 +2111,7 @@
}
}
-static int __init
+static int
imx_uart_console_setup(struct console *co, char *options)
{
struct imx_port *sport;
@@ -2103,39 +2172,6 @@
#define IMX_CONSOLE &imx_uart_console
-#ifdef CONFIG_OF
-static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
-{
- struct imx_port *sport = (struct imx_port *)port;
-
- while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL)
- cpu_relax();
-
- imx_uart_writel(sport, ch, URTX0);
-}
-
-static void imx_uart_console_early_write(struct console *con, const char *s,
- unsigned count)
-{
- struct earlycon_device *dev = con->data;
-
- uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
-}
-
-static int __init
-imx_console_early_setup(struct earlycon_device *dev, const char *opt)
-{
- if (!dev->port.membase)
- return -ENODEV;
-
- dev->con->write = imx_uart_console_early_write;
-
- return 0;
-}
-OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
-OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
-#endif
-
#else
#define IMX_CONSOLE NULL
#endif
@@ -2183,6 +2219,12 @@
if (of_get_property(np, "rts-gpios", NULL))
sport->have_rtsgpio = 1;
+ if (of_get_property(np, "fsl,inverted-tx", NULL))
+ sport->inverted_tx = 1;
+
+ if (of_get_property(np, "fsl,inverted-rx", NULL))
+ sport->inverted_rx = 1;
+
return 0;
}
#else
@@ -2208,6 +2250,32 @@
sport->have_rtscts = 1;
}
+static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t)
+{
+ struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+ if (sport->tx_state == WAIT_AFTER_RTS)
+ imx_uart_start_tx(&sport->port);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
+{
+ struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+ if (sport->tx_state == WAIT_AFTER_SEND)
+ imx_uart_stop_tx(&sport->port);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
static int imx_uart_probe(struct platform_device *pdev)
{
struct imx_port *sport;
@@ -2239,6 +2307,8 @@
return PTR_ERR(base);
rxirq = platform_get_irq(pdev, 0);
+ if (rxirq < 0)
+ return rxirq;
txirq = platform_get_irq_optional(pdev, 1);
rtsirq = platform_get_irq_optional(pdev, 2);
@@ -2249,6 +2319,7 @@
sport->port.iotype = UPIO_MEM;
sport->port.irq = rxirq;
sport->port.fifosize = 32;
+ sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE);
sport->port.ops = &imx_uart_pops;
sport->port.rs485_config = imx_uart_rs485_config;
sport->port.flags = UPF_BOOT_AUTOCONF;
@@ -2288,7 +2359,11 @@
sport->ucr4 = readl(sport->port.membase + UCR4);
sport->ufcr = readl(sport->port.membase + UFCR);
- uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
+ ret = uart_get_rs485_mode(&sport->port);
+ if (ret) {
+ clk_disable_unprepare(sport->clk_ipg);
+ return ret;
+ }
if (sport->port.rs485.flags & SER_RS485_ENABLED &&
(!sport->have_rtscts && !sport->have_rtsgpio))
@@ -2310,8 +2385,7 @@
/* Disable interrupts before requesting them */
ucr1 = imx_uart_readl(sport, UCR1);
- ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
- UCR1_TRDYEN | UCR1_RTSDEN);
+ ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | UCR1_RTSDEN);
imx_uart_writel(sport, ucr1, UCR1);
if (!imx_uart_is_imx1(sport) && sport->dte_mode) {
@@ -2347,6 +2421,11 @@
clk_disable_unprepare(sport->clk_ipg);
+ hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ sport->trigger_start_tx.function = imx_trigger_start_tx;
+ sport->trigger_stop_tx.function = imx_trigger_stop_tx;
+
/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.