From 4183f7df7833fbcd3af776573c1fc7b071a8977f Mon Sep 17 00:00:00 2001 From: Daniel Trnka Date: Sun, 7 Sep 2025 10:08:30 +0200 Subject: [PATCH 1/2] sllin: configure uart RX trigger to 1 byte LIN slave must react immediately when a 3-byte header is received and cannot wait for the RX FIFO to fill or for an idle timeout, which would be driver-dependent. --- sllin/sllin.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sllin/sllin.c b/sllin/sllin.c index 68ab67c..4d2a485 100644 --- a/sllin/sllin.c +++ b/sllin/sllin.c @@ -65,6 +65,7 @@ #include #include #include "linux/lin_bus.h" +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0) #include @@ -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(); From f68c3f8d024303a1faa03e49a550a2c8e288a705 Mon Sep 17 00:00:00 2001 From: Daniel Trnka Date: Sun, 7 Sep 2025 10:41:23 +0200 Subject: [PATCH 2/2] sllin: added kernel patches introducing rx_trigger API --- ...erial-add-rx_trigger-API-to-uart_ops.patch | 71 ++++++++++++++ ...mplementation-of-rx_trigger-uart_ops.patch | 94 +++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 sllin/linux-patches/0001-serial-add-rx_trigger-API-to-uart_ops.patch create mode 100644 sllin/linux-patches/0002-serial-imx-implementation-of-rx_trigger-uart_ops.patch diff --git a/sllin/linux-patches/0001-serial-add-rx_trigger-API-to-uart_ops.patch b/sllin/linux-patches/0001-serial-add-rx_trigger-API-to-uart_ops.patch new file mode 100644 index 0000000..3a67842 --- /dev/null +++ b/sllin/linux-patches/0001-serial-add-rx_trigger-API-to-uart_ops.patch @@ -0,0 +1,71 @@ +From 3d941169431ab9c362412798b8e1702ba4c8a800 Mon Sep 17 00:00:00 2001 +From: Daniel Trnka +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 + diff --git a/sllin/linux-patches/0002-serial-imx-implementation-of-rx_trigger-uart_ops.patch b/sllin/linux-patches/0002-serial-imx-implementation-of-rx_trigger-uart_ops.patch new file mode 100644 index 0000000..33dadba --- /dev/null +++ b/sllin/linux-patches/0002-serial-imx-implementation-of-rx_trigger-uart_ops.patch @@ -0,0 +1,94 @@ +From 639d5c8ccaf36220422f0da422e73577f4276c4b Mon Sep 17 00:00:00 2001 +From: Daniel Trnka +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 +