linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Handle UART without interrupt on TEMT using em485
@ 2021-01-28 23:36 Eric Tremblay
  2021-01-28 23:36 ` [PATCH 1/3] serial: 8250: " Eric Tremblay
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Eric Tremblay @ 2021-01-28 23:36 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, andriy.shevchenko, matwey.kornilov, giulio.benetti,
	lukas, linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner, Eric Tremblay

The series is mainly about the support of 8250 UART without TEMT
interrupt. I saw that there was some development in the past but
it was never merged. Since the last discussion were quite some
time ago, I was not sure if I should post a v4 over the
last v3 or start from scratch so I decided to post a new patch. Please
advice if I should have done the reverse.

The approach is a little different from the last proposed patch which was
doing using a polling at 100us. I tought that it could be really long on 
some fast baudrate and really not that long on slow baudrate. The current
approach is to calculate the time of a bytes when the settings are changed.
When we get the interrupt for the empty FIFO, it's the longer it can take
to empty the shift register.

The other two patches are to use that features with the PORT_16550A_FSL64
found on some chip like the LS1043A.

Thanks

Eric Tremblay (3):
  serial: 8250: Handle UART without interrupt on TEMT using em485
  serial: 8250: add compatible for fsl,16550-FIFO64
  serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64

 drivers/tty/serial/8250/8250.h            |  1 +
 drivers/tty/serial/8250/8250_bcm2835aux.c |  2 +-
 drivers/tty/serial/8250/8250_of.c         |  5 ++
 drivers/tty/serial/8250/8250_omap.c       |  2 +-
 drivers/tty/serial/8250/8250_port.c       | 89 ++++++++++++++++++++++-
 include/linux/serial_8250.h               |  2 +
 6 files changed, 98 insertions(+), 3 deletions(-)

-- 
2.17.1


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

* [PATCH 1/3] serial: 8250: Handle UART without interrupt on TEMT using em485
  2021-01-28 23:36 [PATCH 0/3] Handle UART without interrupt on TEMT using em485 Eric Tremblay
@ 2021-01-28 23:36 ` Eric Tremblay
  2021-01-29  7:23   ` Jiri Slaby
       [not found]   ` <YBPv/EA5LwA6jxId@smile.fi.intel.com>
  2021-01-28 23:36 ` [PATCH 2/3] serial: 8250: add compatible for fsl,16550-FIFO64 Eric Tremblay
  2021-01-28 23:36 ` [PATCH 3/3] serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64 Eric Tremblay
  2 siblings, 2 replies; 9+ messages in thread
From: Eric Tremblay @ 2021-01-28 23:36 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, andriy.shevchenko, matwey.kornilov, giulio.benetti,
	lukas, linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner, Eric Tremblay

The patch introduce the UART_CAP_TEMT capability which is by default
assigned to all 8250 UART since the code assume that device has the
interrupt on TEMT

In the case where the device does not support it, we calculate the
maximum of time it could take for the transmitter to empty the
shift register. When we get in the situation where we get the
THRE interrupt but the TEMT bit is not set we start the timer
and recall __stop_tx after the delay

Signed-off-by: Eric Tremblay <etremblay@distech-controls.com>
---
 drivers/tty/serial/8250/8250.h            |  1 +
 drivers/tty/serial/8250/8250_bcm2835aux.c |  2 +-
 drivers/tty/serial/8250/8250_omap.c       |  2 +-
 drivers/tty/serial/8250/8250_port.c       | 89 ++++++++++++++++++++++-
 include/linux/serial_8250.h               |  2 +
 5 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 52bb21205bb6..5361b761eed7 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -82,6 +82,7 @@ struct serial8250_config {
 #define UART_CAP_MINI	(1 << 17)	/* Mini UART on BCM283X family lacks:
 					 * STOP PARITY EPAR SPAR WLEN5 WLEN6
 					 */
+#define UART_CAP_TEMT	(1 << 18)	/* UART have interrupt on TEMT */
 
 #define UART_BUG_QUOT	(1 << 0)	/* UART has buggy quot LSB */
 #define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
index fd95860cd661..354faebce885 100644
--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
+++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
@@ -91,7 +91,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	/* initialize data */
-	up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
+	data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI | UART_CAP_TEMT;
 	up.port.dev = &pdev->dev;
 	up.port.regshift = 2;
 	up.port.type = PORT_16550;
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 23e0decde33e..1c21ac68ff37 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1294,7 +1294,7 @@ static int omap8250_probe(struct platform_device *pdev)
 	up.port.regshift = 2;
 	up.port.fifosize = 64;
 	up.tx_loadsz = 64;
-	up.capabilities = UART_CAP_FIFO;
+	up.capabilities = UART_CAP_FIFO | UART_CAP_TEMT;
 #ifdef CONFIG_PM
 	/*
 	 * Runtime PM is mostly transparent. However to do it right we need to a
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index b0af13074cd3..44a54406e4b4 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -558,8 +558,41 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
 	}
 }
 
+static inline void serial8250_em485_update_temt_delay(struct uart_8250_port *p,
+			unsigned int cflag, unsigned int baud)
+{
+	unsigned int bits;
+
+	if (!p->em485)
+		return;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	case CS5:
+		bits = 7;
+		break;
+	case CS6:
+		bits = 8;
+		break;
+	case CS7:
+		bits = 9;
+		break;
+	default:
+		bits = 10;
+		break; /* CS8 */
+	}
+
+	if (cflag & CSTOPB)
+		bits++;
+	if (cflag & PARENB)
+		bits++;
+
+	p->em485->no_temt_delay = bits*1000000/baud;
+}
+
 static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
 static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
+static enum hrtimer_restart serial8250_em485_handle_no_temt(struct hrtimer *t);
 
 void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
 {
@@ -618,6 +651,18 @@ static int serial8250_em485_init(struct uart_8250_port *p)
 		     HRTIMER_MODE_REL);
 	hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC,
 		     HRTIMER_MODE_REL);
+
+	if (!(p->capabilities & UART_CAP_TEMT)) {
+		struct tty_struct *tty = p->port.state->port.tty;
+
+		serial8250_em485_update_temt_delay(p, tty->termios.c_cflag,
+						   tty_get_baud_rate(tty));
+		hrtimer_init(&p->em485->no_temt_timer, CLOCK_MONOTONIC,
+			     HRTIMER_MODE_REL);
+		p->em485->no_temt_timer.function =
+			&serial8250_em485_handle_no_temt;
+	}
+
 	p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx;
 	p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
 	p->em485->port = p;
@@ -649,6 +694,7 @@ void serial8250_em485_destroy(struct uart_8250_port *p)
 
 	hrtimer_cancel(&p->em485->start_tx_timer);
 	hrtimer_cancel(&p->em485->stop_tx_timer);
+	hrtimer_cancel(&p->em485->no_temt_timer);
 
 	kfree(p->em485);
 	p->em485 = NULL;
@@ -1494,6 +1540,15 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
 	hrtimer_start(hrt, t, HRTIMER_MODE_REL);
 }
 
+static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec)
+{
+	long sec = usec / 1000000;
+	long nsec = (usec % 1000000) * 1000;
+	ktime_t t = ktime_set(sec, nsec);
+
+	hrtimer_start(hrt, t, HRTIMER_MODE_REL);
+}
+
 static void __stop_tx_rs485(struct uart_8250_port *p)
 {
 	struct uart_8250_em485 *em485 = p->em485;
@@ -1531,8 +1586,18 @@ static inline void __stop_tx(struct uart_8250_port *p)
 		 * shift register are empty. It is for device driver to enable
 		 * interrupt on TEMT.
 		 */
-		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
+		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) {
+			/*
+			 * On devices with no interrupt on TEMT available
+			 * start a timer for a byte time, the timer will recall
+			 * __stop_tx
+			 */
+			if (!(p->capabilities & UART_CAP_TEMT) && (lsr & UART_LSR_THRE)) {
+				em485->active_timer = &em485->no_temt_timer;
+				start_hrtimer_us(&em485->no_temt_timer, em485->no_temt_delay);
+			}
 			return;
+		}
 
 		__stop_tx_rs485(p);
 	}
@@ -1631,6 +1696,25 @@ static inline void start_tx_rs485(struct uart_port *port)
 	__start_tx(port);
 }
 
+static enum hrtimer_restart serial8250_em485_handle_no_temt(struct hrtimer *t)
+{
+	struct uart_8250_em485 *em485;
+	struct uart_8250_port *p;
+	unsigned long flags;
+
+	em485 = container_of(t, struct uart_8250_em485, no_temt_timer);
+	p = em485->port;
+
+	serial8250_rpm_get(p);
+	spin_lock_irqsave(&p->port.lock, flags);
+	if (em485->active_timer == &em485->no_temt_timer)
+		__stop_tx(p);
+
+	spin_unlock_irqrestore(&p->port.lock, flags);
+	serial8250_rpm_put(p);
+	return HRTIMER_NORESTART;
+}
+
 static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t)
 {
 	struct uart_8250_em485 *em485;
@@ -2792,6 +2876,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	serial8250_set_divisor(port, baud, quot, frac);
 
+	if (!(up->capabilities & UART_CAP_TEMT))
+		serial8250_em485_update_temt_delay(up, termios->c_cflag, baud);
+
 	/*
 	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
 	 * is written without DLAB set, this mode will be disabled.
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 9e655055112d..d2c66faff0dd 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -79,7 +79,9 @@ struct uart_8250_ops {
 struct uart_8250_em485 {
 	struct hrtimer		start_tx_timer; /* "rs485 start tx" timer */
 	struct hrtimer		stop_tx_timer;  /* "rs485 stop tx" timer */
+	struct hrtimer		no_temt_timer;  /* "rs485 no tempt interrupt" timer */
 	struct hrtimer		*active_timer;  /* pointer to active timer */
+	unsigned int		no_temt_delay;  /* Value of delay for no TEMT UART */
 	struct uart_8250_port	*port;          /* for hrtimer callbacks */
 	unsigned int		tx_stopped:1;	/* tx is currently stopped */
 };
-- 
2.17.1


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

* [PATCH 2/3] serial: 8250: add compatible for fsl,16550-FIFO64
  2021-01-28 23:36 [PATCH 0/3] Handle UART without interrupt on TEMT using em485 Eric Tremblay
  2021-01-28 23:36 ` [PATCH 1/3] serial: 8250: " Eric Tremblay
@ 2021-01-28 23:36 ` Eric Tremblay
  2021-01-28 23:36 ` [PATCH 3/3] serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64 Eric Tremblay
  2 siblings, 0 replies; 9+ messages in thread
From: Eric Tremblay @ 2021-01-28 23:36 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, andriy.shevchenko, matwey.kornilov, giulio.benetti,
	lukas, linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner, Eric Tremblay

Add the fsl,16550-FIFO64 compatible to be able
to use the port from device-tree

Signed-off-by: Eric Tremblay <etremblay@distech-controls.com>
---
 drivers/tty/serial/8250/8250_of.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 65e9045dafe6..4efc62c0b25c 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -313,6 +313,8 @@ static const struct of_device_id of_platform_serial_table[] = {
 		.data = (void *)PORT_ALTR_16550_F64, },
 	{ .compatible = "altr,16550-FIFO128",
 		.data = (void *)PORT_ALTR_16550_F128, },
+	{ .compatible = "fsl,16550-FIFO64",
+		.data = (void *)PORT_16550A_FSL64, },
 	{ .compatible = "mediatek,mtk-btif",
 		.data = (void *)PORT_MTK_BTIF, },
 	{ .compatible = "mrvl,mmp-uart",
-- 
2.17.1


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

* [PATCH 3/3] serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64
  2021-01-28 23:36 [PATCH 0/3] Handle UART without interrupt on TEMT using em485 Eric Tremblay
  2021-01-28 23:36 ` [PATCH 1/3] serial: 8250: " Eric Tremblay
  2021-01-28 23:36 ` [PATCH 2/3] serial: 8250: add compatible for fsl,16550-FIFO64 Eric Tremblay
@ 2021-01-28 23:36 ` Eric Tremblay
       [not found]   ` <YBPwlmxNfrxSLK0B@smile.fi.intel.com>
  2 siblings, 1 reply; 9+ messages in thread
From: Eric Tremblay @ 2021-01-28 23:36 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, andriy.shevchenko, matwey.kornilov, giulio.benetti,
	lukas, linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner, Eric Tremblay

That port does not have an interrupt on TEMT when using
the FIFO mode.

Signed-off-by: Eric Tremblay <etremblay@distech-controls.com>
---
 drivers/tty/serial/8250/8250_of.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 4efc62c0b25c..9a5bb6837949 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -225,6 +225,9 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 			&port8250.overrun_backoff_time_ms) != 0)
 		port8250.overrun_backoff_time_ms = 0;
 
+	if (port_type != PORT_16550A_FSL64)
+		port8250.capabilities |= UART_CAP_TEMT;
+
 	ret = serial8250_register_8250_port(&port8250);
 	if (ret < 0)
 		goto err_dispose;
-- 
2.17.1


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

* Re: [PATCH 1/3] serial: 8250: Handle UART without interrupt on TEMT using em485
  2021-01-28 23:36 ` [PATCH 1/3] serial: 8250: " Eric Tremblay
@ 2021-01-29  7:23   ` Jiri Slaby
  2021-02-02  0:15     ` Eric Tremblay
       [not found]   ` <YBPv/EA5LwA6jxId@smile.fi.intel.com>
  1 sibling, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2021-01-29  7:23 UTC (permalink / raw)
  To: Eric Tremblay, gregkh
  Cc: andriy.shevchenko, matwey.kornilov, giulio.benetti, lukas,
	linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner

On 29. 01. 21, 0:36, Eric Tremblay wrote:
> The patch introduce the UART_CAP_TEMT capability which is by default
> assigned to all 8250 UART since the code assume that device has the
> interrupt on TEMT
> 
> In the case where the device does not support it, we calculate the
> maximum of time it could take for the transmitter to empty the
> shift register. When we get in the situation where we get the
> THRE interrupt but the TEMT bit is not set we start the timer
> and recall __stop_tx after the delay
> 
> Signed-off-by: Eric Tremblay <etremblay@distech-controls.com>
> ---
>   drivers/tty/serial/8250/8250.h            |  1 +
>   drivers/tty/serial/8250/8250_bcm2835aux.c |  2 +-
>   drivers/tty/serial/8250/8250_omap.c       |  2 +-
>   drivers/tty/serial/8250/8250_port.c       | 89 ++++++++++++++++++++++-
>   include/linux/serial_8250.h               |  2 +
>   5 files changed, 93 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index 52bb21205bb6..5361b761eed7 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -82,6 +82,7 @@ struct serial8250_config {
>   #define UART_CAP_MINI	(1 << 17)	/* Mini UART on BCM283X family lacks:
>   					 * STOP PARITY EPAR SPAR WLEN5 WLEN6
>   					 */
> +#define UART_CAP_TEMT	(1 << 18)	/* UART have interrupt on TEMT */

What about the inversion _NOTEMT? You then set it only on uarts without 
TEMT and don't need to update every single driver.

> diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
> index fd95860cd661..354faebce885 100644
> --- a/drivers/tty/serial/8250/8250_bcm2835aux.c
> +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
> @@ -91,7 +91,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
>   		return -ENOMEM;
>   
>   	/* initialize data */
> -	up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
> +	data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI | UART_CAP_TEMT;

This change looks weird and undocumented. Why do you set data->uart 
suddenly?

Actually, does this build?

>   	up.port.dev = &pdev->dev;
>   	up.port.regshift = 2;
>   	up.port.type = PORT_16550;
> diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
> index 23e0decde33e..1c21ac68ff37 100644
> --- a/drivers/tty/serial/8250/8250_omap.c
> +++ b/drivers/tty/serial/8250/8250_omap.c
> @@ -1294,7 +1294,7 @@ static int omap8250_probe(struct platform_device *pdev)
>   	up.port.regshift = 2;
>   	up.port.fifosize = 64;
>   	up.tx_loadsz = 64;
> -	up.capabilities = UART_CAP_FIFO;
> +	up.capabilities = UART_CAP_FIFO | UART_CAP_TEMT;
>   #ifdef CONFIG_PM
>   	/*
>   	 * Runtime PM is mostly transparent. However to do it right we need to a
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index b0af13074cd3..44a54406e4b4 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -558,8 +558,41 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
>   	}
>   }
>   
> +static inline void serial8250_em485_update_temt_delay(struct uart_8250_port *p,
> +			unsigned int cflag, unsigned int baud)
> +{
> +	unsigned int bits;
> +
> +	if (!p->em485)
> +		return;
> +
> +	/* byte size and parity */
> +	switch (cflag & CSIZE) {
> +	case CS5:
> +		bits = 7;
> +		break;
> +	case CS6:
> +		bits = 8;
> +		break;
> +	case CS7:
> +		bits = 9;
> +		break;
> +	default:
> +		bits = 10;
> +		break; /* CS8 */
> +	}
> +
> +	if (cflag & CSTOPB)
> +		bits++;
> +	if (cflag & PARENB)
> +		bits++;
> +
> +	p->em485->no_temt_delay = bits*1000000/baud;
> +}
> +
>   static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
>   static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
> +static enum hrtimer_restart serial8250_em485_handle_no_temt(struct hrtimer *t);
>   
>   void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
>   {
> @@ -618,6 +651,18 @@ static int serial8250_em485_init(struct uart_8250_port *p)
>   		     HRTIMER_MODE_REL);
>   	hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC,
>   		     HRTIMER_MODE_REL);
> +
> +	if (!(p->capabilities & UART_CAP_TEMT)) {
> +		struct tty_struct *tty = p->port.state->port.tty;

Is this safe? Don't you need a tty reference? Or maybe you need to pass 
the tty from the TIOCSRS485 ioctl to here.

> +		serial8250_em485_update_temt_delay(p, tty->termios.c_cflag,
> +						   tty_get_baud_rate(tty));
> +		hrtimer_init(&p->em485->no_temt_timer, CLOCK_MONOTONIC,
> +			     HRTIMER_MODE_REL);
> +		p->em485->no_temt_timer.function =
> +			&serial8250_em485_handle_no_temt;
> +	}
> +
>   	p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx;
>   	p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
>   	p->em485->port = p;
> @@ -649,6 +694,7 @@ void serial8250_em485_destroy(struct uart_8250_port *p)
>   
>   	hrtimer_cancel(&p->em485->start_tx_timer);
>   	hrtimer_cancel(&p->em485->stop_tx_timer);
> +	hrtimer_cancel(&p->em485->no_temt_timer);
>   
>   	kfree(p->em485);
>   	p->em485 = NULL;
> @@ -1494,6 +1540,15 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
>   	hrtimer_start(hrt, t, HRTIMER_MODE_REL);
>   }
>   
> +static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec)
> +{
> +	long sec = usec / 1000000;
> +	long nsec = (usec % 1000000) * 1000;
> +	ktime_t t = ktime_set(sec, nsec);

Why not ns_to_ktime without all those divisions?

> +
> +	hrtimer_start(hrt, t, HRTIMER_MODE_REL);
> +}
> +
>   static void __stop_tx_rs485(struct uart_8250_port *p)
>   {
>   	struct uart_8250_em485 *em485 = p->em485;
> @@ -1531,8 +1586,18 @@ static inline void __stop_tx(struct uart_8250_port *p)
>   		 * shift register are empty. It is for device driver to enable
>   		 * interrupt on TEMT.
>   		 */
> -		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
> +		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) {
> +			/*
> +			 * On devices with no interrupt on TEMT available
> +			 * start a timer for a byte time, the timer will recall
> +			 * __stop_tx
> +			 */
> +			if (!(p->capabilities & UART_CAP_TEMT) && (lsr & UART_LSR_THRE)) {
> +				em485->active_timer = &em485->no_temt_timer;

How does this interfere with the current handling of active_timer? You 
should explain the changed functionality in the commit log. And you 
don't reset it to NULL in the timer.

> +				start_hrtimer_us(&em485->no_temt_timer, em485->no_temt_delay);
> +			}
>   			return;
> +		}
>   
>   		__stop_tx_rs485(p);
>   	}
> @@ -1631,6 +1696,25 @@ static inline void start_tx_rs485(struct uart_port *port)
>   	__start_tx(port);
>   }
>   
> +static enum hrtimer_restart serial8250_em485_handle_no_temt(struct hrtimer *t)
> +{
> +	struct uart_8250_em485 *em485;
> +	struct uart_8250_port *p;
> +	unsigned long flags;
> +
> +	em485 = container_of(t, struct uart_8250_em485, no_temt_timer);
> +	p = em485->port;
> +
> +	serial8250_rpm_get(p);
> +	spin_lock_irqsave(&p->port.lock, flags);
> +	if (em485->active_timer == &em485->no_temt_timer)
> +		__stop_tx(p);
> +
> +	spin_unlock_irqrestore(&p->port.lock, flags);
> +	serial8250_rpm_put(p);
> +	return HRTIMER_NORESTART;
> +}
> +
>   static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t)
>   {
>   	struct uart_8250_em485 *em485;
> @@ -2792,6 +2876,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
>   
>   	serial8250_set_divisor(port, baud, quot, frac);
>   
> +	if (!(up->capabilities & UART_CAP_TEMT))
> +		serial8250_em485_update_temt_delay(up, termios->c_cflag, baud);
> +
>   	/*
>   	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
>   	 * is written without DLAB set, this mode will be disabled.
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index 9e655055112d..d2c66faff0dd 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -79,7 +79,9 @@ struct uart_8250_ops {
>   struct uart_8250_em485 {
>   	struct hrtimer		start_tx_timer; /* "rs485 start tx" timer */
>   	struct hrtimer		stop_tx_timer;  /* "rs485 stop tx" timer */
> +	struct hrtimer		no_temt_timer;  /* "rs485 no tempt interrupt" timer */
>   	struct hrtimer		*active_timer;  /* pointer to active timer */
> +	unsigned int		no_temt_delay;  /* Value of delay for no TEMT UART */
>   	struct uart_8250_port	*port;          /* for hrtimer callbacks */
>   	unsigned int		tx_stopped:1;	/* tx is currently stopped */
>   };
> 


-- 
js
suse labs

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

* Re: [PATCH 1/3] serial: 8250: Handle UART without interrupt on TEMT using em485
       [not found]   ` <YBPv/EA5LwA6jxId@smile.fi.intel.com>
@ 2021-01-29 16:22     ` Eric Tremblay
  0 siblings, 0 replies; 9+ messages in thread
From: Eric Tremblay @ 2021-01-29 16:22 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: gregkh, jslaby, matwey.kornilov, giulio.benetti, lukas,
	linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner

On 2021-01-29 6:22 a.m., Andy Shevchenko wrote:
> On Thu, Jan 28, 2021 at 06:36:27PM -0500, Eric Tremblay wrote:
>> The patch introduce the UART_CAP_TEMT capability which is by default
>> assigned to all 8250 UART since the code assume that device has the
>> interrupt on TEMT
> You have missed periods in the sentences here and there. Please, check the
> grammar and punctuation everywhere.
>
>> In the case where the device does not support it, we calculate the
>> maximum of time it could take for the transmitter to empty the
> maximum time
>
>> shift register. When we get in the situation where we get the
>> THRE interrupt but the TEMT bit is not set we start the timer
>> and recall __stop_tx after the delay
> __stop_tx()

I will review the grammar and spelling, thanks for mentioning it

>
> ...
>
>>  	/* initialize data */
>> -	up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
>> +	data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI | UART_CAP_TEMT;
> I didn't get, if you state that CAP_TEMT is default on all UARTs, why you have
> this?

It's a merge mistake, sorry for that. The next version will use the 
reverse capability like Jiri Slaby suggested, there will be no needs to
modify other driver.

>
>> -	up.capabilities = UART_CAP_FIFO;
>> +	up.capabilities = UART_CAP_FIFO | UART_CAP_TEMT;
> And so this?
>
> ...
>
>> +static inline void serial8250_em485_update_temt_delay(struct uart_8250_port *p,
>> +			unsigned int cflag, unsigned int baud)
>> +{
>> +	unsigned int bits;
>> +
>> +	if (!p->em485)
>> +		return;
>> +
>> +	/* byte size and parity */
>> +	switch (cflag & CSIZE) {
>> +	case CS5:
>> +		bits = 7;
>> +		break;
>> +	case CS6:
>> +		bits = 8;
>> +		break;
>> +	case CS7:
>> +		bits = 9;
>> +		break;
>> +	default:
>> +		bits = 10;
>> +		break; /* CS8 */
>> +	}
>> +
>> +	if (cflag & CSTOPB)
>> +		bits++;
>> +	if (cflag & PARENB)
>> +		bits++;
> This is repetition of uart_update_timeout(). Find a way to deduplicate.
>
>> +	p->em485->no_temt_delay = bits*1000000/baud;
> Use spaces.
> Is this magic should be defined as HZ_PER_MHZ?
>
>> +}
> ...
>
>> +static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec)
>> +{
>> +	long sec = usec / 1000000;
>> +	long nsec = (usec % 1000000) * 1000;
>
> USEC_PER_SEC
> NSEC_PER_USEC
>
>> +	ktime_t t = ktime_set(sec, nsec);
>> +
>> +	hrtimer_start(hrt, t, HRTIMER_MODE_REL);
>> +}
> ...
>
>> +		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) {
>> +			/*
>> +			 * On devices with no interrupt on TEMT available
> "with no TEMT interrupt available"
>
>> +			 * start a timer for a byte time, the timer will recall
>> +			 * __stop_tx
> __stop_tx().
>
>> +			 */
>> +			if (!(p->capabilities & UART_CAP_TEMT) && (lsr & UART_LSR_THRE)) {
>> +				em485->active_timer = &em485->no_temt_timer;
>> +				start_hrtimer_us(&em485->no_temt_timer, em485->no_temt_delay);
>> +			}
> Perhaps
> 			if ((p->capabilities & UART_CAP_TEMT) && (lsr & UART_LSR_THRE))
> 				return;
>
> 			em485->active_timer = &em485->no_temt_timer;
> 			start_hrtimer_us(&em485->no_temt_timer, em485->no_temt_delay);
>
> ?

I also prefer that form, I will apply it in next version

>
>>  			return;
>> +		}



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

* Re: [PATCH 3/3] serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64
       [not found]   ` <YBPwlmxNfrxSLK0B@smile.fi.intel.com>
@ 2021-01-29 18:04     ` Eric Tremblay
  2021-01-29 18:42       ` Andy Shevchenko
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Tremblay @ 2021-01-29 18:04 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: gregkh, jslaby, matwey.kornilov, giulio.benetti, lukas,
	linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner

On 2021-01-29 6:25 a.m., Andy Shevchenko wrote:
> On Thu, Jan 28, 2021 at 06:36:29PM -0500, Eric Tremblay wrote:
>> That port does not have an interrupt on TEMT when using
>> the FIFO mode.
> This is wrong.
> 1. You have to guarantee that TEMT is set for all UARTs before this patch
> 2. World is not staying on OF only platforms
>
> NAK

Considering the use of the reversed capability UART_CAP_NOTEMT should I set
the flag directly in uart_config like:

[PORT_16550A_FSL64] = {
		.name		= "16550A_FSL64",
		.fifo_size	= 64,
		.tx_loadsz	= 63,
		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
				  UART_FCR7_64BYTE,
		.flags		= UART_CAP_FIFO | UART_CAP_NOTEMT,
	},

>


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

* Re: [PATCH 3/3] serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64
  2021-01-29 18:04     ` Eric Tremblay
@ 2021-01-29 18:42       ` Andy Shevchenko
  0 siblings, 0 replies; 9+ messages in thread
From: Andy Shevchenko @ 2021-01-29 18:42 UTC (permalink / raw)
  To: Eric Tremblay
  Cc: Andy Shevchenko, Greg Kroah-Hartman, Jiri Slaby,
	Matwey V. Kornilov, Giulio Benetti, Lukas Wunner,
	open list:SERIAL DRIVERS, Linux Kernel Mailing List,
	christoph.muellner, Heiko Stübner, Heiko Stuebner

On Fri, Jan 29, 2021 at 8:07 PM Eric Tremblay
<etremblay@distech-controls.com> wrote:
> On 2021-01-29 6:25 a.m., Andy Shevchenko wrote:

...

> Considering the use of the reversed capability UART_CAP_NOTEMT should I set
> the flag directly in uart_config like:
>
> [PORT_16550A_FSL64] = {
>                 .name           = "16550A_FSL64",
>                 .fifo_size      = 64,
>                 .tx_loadsz      = 63,
>                 .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
>                                   UART_FCR7_64BYTE,
>                 .flags          = UART_CAP_FIFO | UART_CAP_NOTEMT,
>         },

This looks much better!

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 1/3] serial: 8250: Handle UART without interrupt on TEMT using em485
  2021-01-29  7:23   ` Jiri Slaby
@ 2021-02-02  0:15     ` Eric Tremblay
  0 siblings, 0 replies; 9+ messages in thread
From: Eric Tremblay @ 2021-02-02  0:15 UTC (permalink / raw)
  To: Jiri Slaby, gregkh
  Cc: andriy.shevchenko, matwey.kornilov, giulio.benetti, lukas,
	linux-serial, linux-kernel, christoph.muellner, heiko,
	heiko.stuebner

On 2021-01-29 2:23 a.m., Jiri Slaby wrote:
> On 29. 01. 21, 0:36, Eric Tremblay wrote:
>> The patch introduce the UART_CAP_TEMT capability which is by default
>> assigned to all 8250 UART since the code assume that device has the
>> interrupt on TEMT
>>
>> In the case where the device does not support it, we calculate the
>> maximum of time it could take for the transmitter to empty the
>> shift register. When we get in the situation where we get the
>> THRE interrupt but the TEMT bit is not set we start the timer
>> and recall __stop_tx after the delay
>>
>> Signed-off-by: Eric Tremblay <etremblay@distech-controls.com>
>> ---
>>   drivers/tty/serial/8250/8250.h            |  1 +
>>   drivers/tty/serial/8250/8250_bcm2835aux.c |  2 +-
>>   drivers/tty/serial/8250/8250_omap.c       |  2 +-
>>   drivers/tty/serial/8250/8250_port.c       | 89 ++++++++++++++++++++++-
>>   include/linux/serial_8250.h               |  2 +
>>   5 files changed, 93 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
>> index 52bb21205bb6..5361b761eed7 100644
>> --- a/drivers/tty/serial/8250/8250.h
>> +++ b/drivers/tty/serial/8250/8250.h
>> @@ -82,6 +82,7 @@ struct serial8250_config {
>>   #define UART_CAP_MINI    (1 << 17)    /* Mini UART on BCM283X family lacks:
>>                        * STOP PARITY EPAR SPAR WLEN5 WLEN6
>>                        */
>> +#define UART_CAP_TEMT    (1 << 18)    /* UART have interrupt on TEMT */
>
> What about the inversion _NOTEMT? You then set it only on uarts without TEMT and don't need to update every single driver.
That's a good Idea, I will use that in the next version.
>
>> diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
>> index fd95860cd661..354faebce885 100644
>> --- a/drivers/tty/serial/8250/8250_bcm2835aux.c
>> +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
>> @@ -91,7 +91,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
>>           return -ENOMEM;
>>         /* initialize data */
>> -    up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
>> +    data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI | UART_CAP_TEMT;
>
> This change looks weird and undocumented. Why do you set data->uart suddenly?
>
> Actually, does this build?

This is a silly merge mistake, sorry about that. However, it will not be there

in the next version with the _NOTEMT capability.

>
>>       up.port.dev = &pdev->dev;
>>       up.port.regshift = 2;
>>       up.port.type = PORT_16550;
>> diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
>> index 23e0decde33e..1c21ac68ff37 100644
>> --- a/drivers/tty/serial/8250/8250_omap.c
>> +++ b/drivers/tty/serial/8250/8250_omap.c
>> @@ -1294,7 +1294,7 @@ static int omap8250_probe(struct platform_device *pdev)
>>       up.port.regshift = 2;
>>       up.port.fifosize = 64;
>>       up.tx_loadsz = 64;
>> -    up.capabilities = UART_CAP_FIFO;
>> +    up.capabilities = UART_CAP_FIFO | UART_CAP_TEMT;
>>   #ifdef CONFIG_PM
>>       /*
>>        * Runtime PM is mostly transparent. However to do it right we need to a
>> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
>> index b0af13074cd3..44a54406e4b4 100644
>> --- a/drivers/tty/serial/8250/8250_port.c
>> +++ b/drivers/tty/serial/8250/8250_port.c
>> @@ -558,8 +558,41 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
>>       }
>>   }
>>   +static inline void serial8250_em485_update_temt_delay(struct uart_8250_port *p,
>> +            unsigned int cflag, unsigned int baud)
>> +{
>> +    unsigned int bits;
>> +
>> +    if (!p->em485)
>> +        return;
>> +
>> +    /* byte size and parity */
>> +    switch (cflag & CSIZE) {
>> +    case CS5:
>> +        bits = 7;
>> +        break;
>> +    case CS6:
>> +        bits = 8;
>> +        break;
>> +    case CS7:
>> +        bits = 9;
>> +        break;
>> +    default:
>> +        bits = 10;
>> +        break; /* CS8 */
>> +    }
>> +
>> +    if (cflag & CSTOPB)
>> +        bits++;
>> +    if (cflag & PARENB)
>> +        bits++;
>> +
>> +    p->em485->no_temt_delay = bits*1000000/baud;
>> +}
>> +
>>   static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
>>   static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
>> +static enum hrtimer_restart serial8250_em485_handle_no_temt(struct hrtimer *t);
>>     void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
>>   {
>> @@ -618,6 +651,18 @@ static int serial8250_em485_init(struct uart_8250_port *p)
>>                HRTIMER_MODE_REL);
>>       hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC,
>>                HRTIMER_MODE_REL);
>> +
>> +    if (!(p->capabilities & UART_CAP_TEMT)) {
>> +        struct tty_struct *tty = p->port.state->port.tty;
>
> Is this safe? Don't you need a tty reference? Or maybe you need to pass the tty from the TIOCSRS485 ioctl to here.
I saw that there was some place in the code where the tty_struct or the termios struct
was accessed that way, I may have done a wrong assumption. To get the TTY struct from the IOCTL,
we will need to modify the rs485_config() callback, I'm not sure I want to go there.

Is using tty_port_initialized() before and returning an error on failure would be a sufficient
safety check ?
>
>> +        serial8250_em485_update_temt_delay(p, tty->termios.c_cflag,
>> +                           tty_get_baud_rate(tty));
>> +        hrtimer_init(&p->em485->no_temt_timer, CLOCK_MONOTONIC,
>> +                 HRTIMER_MODE_REL);
>> +        p->em485->no_temt_timer.function =
>> +            &serial8250_em485_handle_no_temt;
>> +    }
>> +
>>       p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx;
>>       p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
>>       p->em485->port = p;
>> @@ -649,6 +694,7 @@ void serial8250_em485_destroy(struct uart_8250_port *p)
>>         hrtimer_cancel(&p->em485->start_tx_timer);
>>       hrtimer_cancel(&p->em485->stop_tx_timer);
>> +    hrtimer_cancel(&p->em485->no_temt_timer);
>>         kfree(p->em485);
>>       p->em485 = NULL;
>> @@ -1494,6 +1540,15 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
>>       hrtimer_start(hrt, t, HRTIMER_MODE_REL);
>>   }
>>   +static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec)
>> +{
>> +    long sec = usec / 1000000;
>> +    long nsec = (usec % 1000000) * 1000;
>> +    ktime_t t = ktime_set(sec, nsec);
>
> Why not ns_to_ktime without all those divisions?

I will change the timer to _ns and use that function, thanks.

>
>> +
>> +    hrtimer_start(hrt, t, HRTIMER_MODE_REL);
>> +}
>> +
>>   static void __stop_tx_rs485(struct uart_8250_port *p)
>>   {
>>       struct uart_8250_em485 *em485 = p->em485;
>> @@ -1531,8 +1586,18 @@ static inline void __stop_tx(struct uart_8250_port *p)
>>            * shift register are empty. It is for device driver to enable
>>            * interrupt on TEMT.
>>            */
>> -        if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
>> +        if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) {
>> +            /*
>> +             * On devices with no interrupt on TEMT available
>> +             * start a timer for a byte time, the timer will recall
>> +             * __stop_tx
>> +             */
>> +            if (!(p->capabilities & UART_CAP_TEMT) && (lsr & UART_LSR_THRE)) {
>> +                em485->active_timer = &em485->no_temt_timer;
>
> How does this interfere with the current handling of active_timer? You should explain the changed functionality in the commit log. And you don't reset it to NULL in the timer.
I will add that information in the commit message thanks.
>
>> +                start_hrtimer_us(&em485->no_temt_timer, em485->no_temt_delay);
>> +            }
>>               return;
>> +        }
>>             __stop_tx_rs485(p);
>>       }
>> @@ -1631,6 +1696,25 @@ static inline void start_tx_rs485(struct uart_port *port)
>>       __start_tx(port);
>>   }
>>   +static enum hrtimer_restart serial8250_em485_handle_no_temt(struct hrtimer *t)
>> +{
>> +    struct uart_8250_em485 *em485;
>> +    struct uart_8250_port *p;
>> +    unsigned long flags;
>> +
>> +    em485 = container_of(t, struct uart_8250_em485, no_temt_timer);
>> +    p = em485->port;
>> +
>> +    serial8250_rpm_get(p);
>> +    spin_lock_irqsave(&p->port.lock, flags);
>> +    if (em485->active_timer == &em485->no_temt_timer)
>> +        __stop_tx(p);
>> +
>> +    spin_unlock_irqrestore(&p->port.lock, flags);
>> +    serial8250_rpm_put(p);
>> +    return HRTIMER_NORESTART;
>> +}
>> +
>>   static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t)
>>   {
>>       struct uart_8250_em485 *em485;
>> @@ -2792,6 +2876,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
>>         serial8250_set_divisor(port, baud, quot, frac);
>>   +    if (!(up->capabilities & UART_CAP_TEMT))
>> +        serial8250_em485_update_temt_delay(up, termios->c_cflag, baud);
>> +
>>       /*
>>        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
>>        * is written without DLAB set, this mode will be disabled.
>> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
>> index 9e655055112d..d2c66faff0dd 100644
>> --- a/include/linux/serial_8250.h
>> +++ b/include/linux/serial_8250.h
>> @@ -79,7 +79,9 @@ struct uart_8250_ops {
>>   struct uart_8250_em485 {
>>       struct hrtimer        start_tx_timer; /* "rs485 start tx" timer */
>>       struct hrtimer        stop_tx_timer;  /* "rs485 stop tx" timer */
>> +    struct hrtimer        no_temt_timer;  /* "rs485 no tempt interrupt" timer */
>>       struct hrtimer        *active_timer;  /* pointer to active timer */
>> +    unsigned int        no_temt_delay;  /* Value of delay for no TEMT UART */
>>       struct uart_8250_port    *port;          /* for hrtimer callbacks */
>>       unsigned int        tx_stopped:1;    /* tx is currently stopped */
>>   };
>>
>
>


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

end of thread, other threads:[~2021-02-02  0:17 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-28 23:36 [PATCH 0/3] Handle UART without interrupt on TEMT using em485 Eric Tremblay
2021-01-28 23:36 ` [PATCH 1/3] serial: 8250: " Eric Tremblay
2021-01-29  7:23   ` Jiri Slaby
2021-02-02  0:15     ` Eric Tremblay
     [not found]   ` <YBPv/EA5LwA6jxId@smile.fi.intel.com>
2021-01-29 16:22     ` Eric Tremblay
2021-01-28 23:36 ` [PATCH 2/3] serial: 8250: add compatible for fsl,16550-FIFO64 Eric Tremblay
2021-01-28 23:36 ` [PATCH 3/3] serial: 8250: remove UART_CAP_TEMT on PORT_16550A_FSL64 Eric Tremblay
     [not found]   ` <YBPwlmxNfrxSLK0B@smile.fi.intel.com>
2021-01-29 18:04     ` Eric Tremblay
2021-01-29 18:42       ` Andy Shevchenko

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