Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
From 3d941169431ab9c362412798b8e1702ba4c8a800 Mon Sep 17 00:00:00 2001
From: Daniel Trnka <[email protected]>
Date: Sun, 7 Sep 2025 09:34:29 +0200
Subject: [PATCH 1/2] serial: add rx_trigger API to uart_ops

Introduce rx_trigger() callback in struct uart_ops to configure
RX FIFO trigger conditions based on the number of received bytes
or an idle timeout in nanoseconds. This allows communication
protocols to react immediately to incoming data without waiting
for the RX buffer to fill or for a timeout.
---
include/linux/serial_core.h | 21 +++++++++++++++++++++
include/uapi/linux/serial_core.h | 5 +++++
2 files changed, 26 insertions(+)

diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 84b4648ead7..ef2bfe2478d 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -344,6 +344,25 @@ struct gpio_desc;
* Locking: none.
* Interrupts: caller dependent.
*
+ * @rx_trigger: ``int (*)(struct uart_port *port, int mode,
+ * int *rx_trigger_bytes, int *rx_trigger_idle_time)``
+ *
+ * Configure the RX trigger condition based on either the number of received
+ * bytes or a period of RX line idleness, expressed in nanoseconds.
+ *
+ * Supported @mode:
+ * UART_RX_TRIGGER_MODE_SET
+ * Apply the trigger using the values in @rx_trigger_bytes and
+ * @rx_trigger_idle_time.
+ * UART_RX_TRIGGER_MODE_CHECK_ROUND_DOWN
+ * UART_RX_TRIGGER_MODE_CHECK_ROUND_UP
+ * Round the requested values down or up to the nearest hardware-
+ * supported value. The adjusted values are written back to
+ * @rx_trigger_bytes and @rx_trigger_idle_time.
+ * UART_RX_TRIGGER_MODE_GET
+ * Return the currently configured trigger values via
+ * @rx_trigger_bytes and @rx_trigger_idle_time.
+ *
* @poll_init: ``int ()(struct uart_port *port)``
*
* Called by kgdb to perform the minimal hardware initialization needed to
@@ -399,6 +418,8 @@ struct uart_ops {
void (*config_port)(struct uart_port *, int);
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
+ int (*rx_trigger)(struct uart_port *, int mode, int *rx_trigger_bytes,
+ int *rx_trigger_idle_time);
#ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 9c007a10633..e3445d4edc9 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -234,4 +234,9 @@
/* Generic type identifier for ports which type is not important to userspace. */
#define PORT_GENERIC (-1)

+#define UART_RX_TRIGGER_MODE_SET 0
+#define UART_RX_TRIGGER_MODE_CHECK_ROUND_DOWN 1
+#define UART_RX_TRIGGER_MODE_CHECK_ROUND_UP 2
+#define UART_RX_TRIGGER_MODE_GET 3
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
2.34.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
From 639d5c8ccaf36220422f0da422e73577f4276c4b Mon Sep 17 00:00:00 2001
From: Daniel Trnka <[email protected]>
Date: Sun, 7 Sep 2025 09:46:01 +0200
Subject: [PATCH 2/2] serial: imx: implementation of rx_trigger uart_ops

- rx_trigger_bytes can be between 1 and 32
- rx_trigger_idle_time not supported (AGTIM fixed at 8 characters)
---
drivers/tty/serial/imx.c | 55 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 500dfc009d0..6ac5988ba34 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -175,6 +175,7 @@
#define DRIVER_NAME "IMX-uart"

#define UART_NR 8
+#define FIFO_MAX_DEPTH 32

/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
enum imx_uart_type {
@@ -2054,6 +2055,59 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
return 0;
}

+/*
+ * rx_trigger_bytes can be between 1 and 32
+ * rx_trigger_idle_time is unsupported - AGTIM is fixed at 8 characters
+ */
+static int imx_uart_rx_trigger(struct uart_port *port, int mode,
+ int *rx_trigger_bytes, int *rx_trigger_idle_time)
+{
+ struct imx_port *sport = to_imx_port(port);
+ u32 ufcr;
+ unsigned int txwl, rxwl;
+
+ if (rx_trigger_idle_time) {
+ return -ENOTSUPP;
+ }
+
+ if (!rx_trigger_bytes) {
+ return -EINVAL;
+ }
+
+ /* read currently set FIFO thresholds */
+ ufcr = imx_uart_readl(sport, UFCR);
+ rxwl = (ufcr >> UFCR_RXTL_SHF) & UFCR_RXTL_MASK;
+ txwl = ufcr >> UFCR_TXTL_SHF;
+
+ switch (mode) {
+ case UART_RX_TRIGGER_MODE_SET:
+ if (*rx_trigger_bytes < 1 || *rx_trigger_bytes > FIFO_MAX_DEPTH) {
+ return -EINVAL;
+ }
+
+ imx_uart_setup_ufcr(sport, txwl, *rx_trigger_bytes);
+ break;
+
+ case UART_RX_TRIGGER_MODE_CHECK_ROUND_DOWN:
+ case UART_RX_TRIGGER_MODE_CHECK_ROUND_UP:
+ if (*rx_trigger_bytes < 1) {
+ *rx_trigger_bytes = 1;
+ }
+
+ if (*rx_trigger_bytes > FIFO_MAX_DEPTH) {
+ *rx_trigger_bytes = FIFO_MAX_DEPTH;
+ }
+
+ break;
+ case UART_RX_TRIGGER_MODE_GET:
+ *rx_trigger_bytes = rxwl;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ return 0;
+}
+
static const struct uart_ops imx_uart_pops = {
.tx_empty = imx_uart_tx_empty,
.set_mctrl = imx_uart_set_mctrl,
@@ -2070,6 +2124,7 @@ static const struct uart_ops imx_uart_pops = {
.type = imx_uart_type,
.config_port = imx_uart_config_port,
.verify_port = imx_uart_verify_port,
+ .rx_trigger = imx_uart_rx_trigger,
#if defined(CONFIG_CONSOLE_POLL)
.poll_init = imx_uart_poll_init,
.poll_get_char = imx_uart_poll_get_char,
--
2.34.1

15 changes: 15 additions & 0 deletions sllin/sllin.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include <linux/hrtimer.h>
#include <linux/version.h>
#include "linux/lin_bus.h"
#include <linux/serial_core.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)
#include <uapi/linux/sched/types.h>
Expand Down Expand Up @@ -1678,6 +1679,20 @@ static int sllin_open_common(struct tty_struct *tty, bool setup_master)
*/
rtnl_lock();

#ifdef UART_RX_TRIGGER_MODE_SET
struct uart_state *state = tty->driver_data;
if (state) {
struct uart_port *uport = state->uart_port;
if (uport && uport->ops->rx_trigger) {
int rx_trigger_bytes = 1;
err = uport->ops->rx_trigger(uport, UART_RX_TRIGGER_MODE_SET, &rx_trigger_bytes, NULL);
if (err) {
pr_err("sllin: Failed to configure rx_trigger: %d", err);
}
}
}
#endif

/* Collect hanged up channels. */
sll_sync();

Expand Down