* [PATCH v7 1/4] serial: 8250_dwlib: move DesignWare register definitions to header
From: Jia Wang @ 2026-04-29 9:13 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang
In-Reply-To: <20260429-ultrarisc-serial-v7-0-e475cce9e274@ultrarisc.com>
Move the DW_UART_* register offsets and CPR bit/field definitions from
8250_dwlib.c into 8250_dwlib.h so they can be shared by 8250_dw and
8250_dwlib users.
Add an include guard for 8250_dwlib.h.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 11 ------
drivers/tty/serial/8250/8250_dwlib.c | 49 --------------------------
drivers/tty/serial/8250/8250_dwlib.h | 67 ++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+), 60 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 94beadb4024d..467755bf0092 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -34,22 +34,11 @@
#include "8250_dwlib.h"
-/* Offsets for the DesignWare specific registers */
-#define DW_UART_USR 0x1f /* UART Status Register */
-#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
-
#define OCTEON_UART_USR 0x27 /* UART Status Register */
#define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */
#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
-/* DesignWare specific register fields */
-#define DW_UART_IIR_IID GENMASK(3, 0)
-
-#define DW_UART_MCR_SIRE BIT(6)
-
-#define DW_UART_USR_BUSY BIT(0)
-
/* Renesas specific register fields */
#define RZN1_UART_xDMACR_DMA_EN BIT(0)
#define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1)
diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index b055d89cfb39..8859e66d2d71 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -13,55 +13,6 @@
#include "8250_dwlib.h"
-/* Offsets for the DesignWare specific registers */
-#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */
-#define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */
-#define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */
-#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
-#define DW_UART_RAR 0xc4 /* Receive Address Register */
-#define DW_UART_TAR 0xc8 /* Transmit Address Register */
-#define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */
-#define DW_UART_CPR 0xf4 /* Component Parameter Register */
-#define DW_UART_UCV 0xf8 /* UART Component Version */
-
-/* Receive / Transmit Address Register bits */
-#define DW_UART_ADDR_MASK GENMASK(7, 0)
-
-/* Line Status Register bits */
-#define DW_UART_LSR_ADDR_RCVD BIT(8)
-
-/* Transceiver Control Register bits */
-#define DW_UART_TCR_RS485_EN BIT(0)
-#define DW_UART_TCR_RE_POL BIT(1)
-#define DW_UART_TCR_DE_POL BIT(2)
-#define DW_UART_TCR_XFER_MODE GENMASK(4, 3)
-#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
-#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
-#define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
-
-/* Line Extended Control Register bits */
-#define DW_UART_LCR_EXT_DLS_E BIT(0)
-#define DW_UART_LCR_EXT_ADDR_MATCH BIT(1)
-#define DW_UART_LCR_EXT_SEND_ADDR BIT(2)
-#define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3)
-
-/* Component Parameter Register bits */
-#define DW_UART_CPR_ABP_DATA_WIDTH GENMASK(1, 0)
-#define DW_UART_CPR_AFCE_MODE BIT(4)
-#define DW_UART_CPR_THRE_MODE BIT(5)
-#define DW_UART_CPR_SIR_MODE BIT(6)
-#define DW_UART_CPR_SIR_LP_MODE BIT(7)
-#define DW_UART_CPR_ADDITIONAL_FEATURES BIT(8)
-#define DW_UART_CPR_FIFO_ACCESS BIT(9)
-#define DW_UART_CPR_FIFO_STAT BIT(10)
-#define DW_UART_CPR_SHADOW BIT(11)
-#define DW_UART_CPR_ENCODED_PARMS BIT(12)
-#define DW_UART_CPR_DMA_EXTRA BIT(13)
-#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16)
-
-/* Helper for FIFO size calculation */
-#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16)
-
/*
* divisor = div(I) + div(F)
* "I" means integer, "F" means fractional
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 7dd2a8e7b780..2f26f9ecacbe 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -1,11 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Synopsys DesignWare 8250 library header file. */
+#ifndef _SERIAL_8250_DWLIB_H_
+#define _SERIAL_8250_DWLIB_H_
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
#include <linux/io.h>
#include <linux/types.h>
#include "8250.h"
+/* Offsets for the DesignWare specific registers */
+#define DW_UART_USR 0x1f /* UART Status Register */
+#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
+#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */
+#define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */
+#define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */
+#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
+#define DW_UART_RAR 0xc4 /* Receive Address Register */
+#define DW_UART_TAR 0xc8 /* Transmit Address Register */
+#define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */
+#define DW_UART_CPR 0xf4 /* Component Parameter Register */
+#define DW_UART_UCV 0xf8 /* UART Component Version */
+
+/* Interrupt ID Register bits */
+#define DW_UART_IIR_IID GENMASK(3, 0)
+
+/* Modem Control Register bits */
+#define DW_UART_MCR_SIRE BIT(6)
+
+/* Line Status Register bits */
+#define DW_UART_LSR_ADDR_RCVD BIT(8)
+
+/* UART Status Register bits */
+#define DW_UART_USR_BUSY BIT(0)
+
+/* Transceiver Control Register bits */
+#define DW_UART_TCR_RS485_EN BIT(0)
+#define DW_UART_TCR_RE_POL BIT(1)
+#define DW_UART_TCR_DE_POL BIT(2)
+#define DW_UART_TCR_XFER_MODE GENMASK(4, 3)
+#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
+#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
+#define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
+
+/* Receive / Transmit Address Register bits */
+#define DW_UART_ADDR_MASK GENMASK(7, 0)
+
+/* Line Extended Control Register bits */
+#define DW_UART_LCR_EXT_DLS_E BIT(0)
+#define DW_UART_LCR_EXT_ADDR_MATCH BIT(1)
+#define DW_UART_LCR_EXT_SEND_ADDR BIT(2)
+#define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3)
+
+/* Component Parameter Register bits */
+#define DW_UART_CPR_ABP_DATA_WIDTH GENMASK(1, 0)
+#define DW_UART_CPR_AFCE_MODE BIT(4)
+#define DW_UART_CPR_THRE_MODE BIT(5)
+#define DW_UART_CPR_SIR_MODE BIT(6)
+#define DW_UART_CPR_SIR_LP_MODE BIT(7)
+#define DW_UART_CPR_ADDITIONAL_FEATURES BIT(8)
+#define DW_UART_CPR_FIFO_ACCESS BIT(9)
+#define DW_UART_CPR_FIFO_STAT BIT(10)
+#define DW_UART_CPR_SHADOW BIT(11)
+#define DW_UART_CPR_ENCODED_PARMS BIT(12)
+#define DW_UART_CPR_DMA_EXTRA BIT(13)
+#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16)
+
+/* Helper for FIFO size calculation */
+#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16)
+
struct dw8250_port_data {
/* Port properties */
int line;
@@ -38,3 +103,5 @@ static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
else
writel(reg, p->membase + offset);
}
+
+#endif /* _SERIAL_8250_DWLIB_H_ */
--
2.34.1
^ permalink raw reply related
* [PATCH v7 2/4] serial: 8250_dw: build Renesas RZN1 CPR value from DW_UART_CPR_* definitions
From: Jia Wang @ 2026-04-29 9:13 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang
In-Reply-To: <20260429-ultrarisc-serial-v7-0-e475cce9e274@ultrarisc.com>
Replace the magic CPR value for Renesas RZ/N1 with a composition using
DW_UART_CPR_* bit/field definitions and FIELD_PREP_CONST().
Introduce a helper macro to convert a FIFO size (bytes) into the CPR
FIFO_MODE field value, with BUILD_BUG_ON_ZERO() checks for alignment and
bounds. Use it to replace the literal FIFO_MODE values in the RZN1.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
drivers/tty/serial/8250/8250_dw.c | 10 +++++++++-
drivers/tty/serial/8250/8250_dwlib.h | 8 +++++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 467755bf0092..480f82d89856 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -937,7 +937,15 @@ static const struct dw8250_platform_data dw8250_armada_38x_data = {
static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
.usr_reg = DW_UART_USR,
- .cpr_value = 0x00012f32,
+ .cpr_value = FIELD_PREP_CONST(DW_UART_CPR_ABP_DATA_WIDTH, 2) |
+ DW_UART_CPR_AFCE_MODE |
+ DW_UART_CPR_THRE_MODE |
+ DW_UART_CPR_ADDITIONAL_FEATURES |
+ DW_UART_CPR_FIFO_ACCESS |
+ DW_UART_CPR_FIFO_STAT |
+ DW_UART_CPR_SHADOW |
+ DW_UART_CPR_DMA_EXTRA |
+ DW_UART_CPR_FIFO_MODE_FROM_SIZE(16),
.quirks = DW_UART_QUIRK_CPR_VALUE | DW_UART_QUIRK_IS_DMA_FC,
};
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 2f26f9ecacbe..1fe52332e774 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -6,6 +6,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/build_bug.h>
#include <linux/io.h>
#include <linux/types.h>
@@ -68,8 +69,13 @@
#define DW_UART_CPR_DMA_EXTRA BIT(13)
#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16)
-/* Helper for FIFO size calculation */
+/* Helpers for FIFO size calculation */
#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16)
+#define DW_UART_CPR_FIFO_MODE_FROM_SIZE(size) \
+ (FIELD_PREP_CONST(DW_UART_CPR_FIFO_MODE, \
+ BUILD_BUG_ON_ZERO((size) > 2048) + \
+ BUILD_BUG_ON_ZERO((size) % 16) + \
+ ((size) / 16)))
struct dw8250_port_data {
/* Port properties */
--
2.34.1
^ permalink raw reply related
* [PATCH v7 4/4] serial: 8250_dw: Use a fixed CPR value for UltraRISC DP1000 UART
From: Jia Wang @ 2026-04-29 9:13 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang
In-Reply-To: <20260429-ultrarisc-serial-v7-0-e475cce9e274@ultrarisc.com>
The UltraRISC DP1000 UART does not provide the standard CPR register used
by 8250_dw to discover port capabilities.
Provide a fixed CPR value for the DP1000-specific compatible so the
driver can configure the port correctly.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 480f82d89856..55e40c10f46a 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -959,6 +959,15 @@ static const struct dw8250_platform_data dw8250_intc10ee = {
.quirks = DW_UART_QUIRK_IER_KICK,
};
+static const struct dw8250_platform_data dw8250_ultrarisc_dp1000_data = {
+ .usr_reg = DW_UART_USR,
+ .cpr_value = FIELD_PREP_CONST(DW_UART_CPR_ABP_DATA_WIDTH, 2) |
+ DW_UART_CPR_THRE_MODE |
+ DW_UART_CPR_DMA_EXTRA |
+ DW_UART_CPR_FIFO_MODE_FROM_SIZE(32),
+ .quirks = DW_UART_QUIRK_CPR_VALUE,
+};
+
static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
@@ -966,6 +975,7 @@ static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
{ .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
{ .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
+ { .compatible = "ultrarisc,dp1000-uart", .data = &dw8250_ultrarisc_dp1000_data },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
--
2.34.1
^ permalink raw reply related
* [PATCH v6 1/4] serial: 8250_dwlib: move DesignWare register definitions to header
From: Jia Wang @ 2026-04-29 9:05 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang
In-Reply-To: <20260429-ultrarisc-serial-v6-0-b2c852e0c4c3@ultrarisc.com>
Move the DW_UART_* register offsets and CPR bit/field definitions from
8250_dwlib.c into 8250_dwlib.h so they can be shared by 8250_dw and
8250_dwlib users.
Add an include guard for 8250_dwlib.h.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 11 ------
drivers/tty/serial/8250/8250_dwlib.c | 49 --------------------------
drivers/tty/serial/8250/8250_dwlib.h | 67 ++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+), 60 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 94beadb4024d..467755bf0092 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -34,22 +34,11 @@
#include "8250_dwlib.h"
-/* Offsets for the DesignWare specific registers */
-#define DW_UART_USR 0x1f /* UART Status Register */
-#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
-
#define OCTEON_UART_USR 0x27 /* UART Status Register */
#define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */
#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
-/* DesignWare specific register fields */
-#define DW_UART_IIR_IID GENMASK(3, 0)
-
-#define DW_UART_MCR_SIRE BIT(6)
-
-#define DW_UART_USR_BUSY BIT(0)
-
/* Renesas specific register fields */
#define RZN1_UART_xDMACR_DMA_EN BIT(0)
#define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1)
diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index b055d89cfb39..8859e66d2d71 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -13,55 +13,6 @@
#include "8250_dwlib.h"
-/* Offsets for the DesignWare specific registers */
-#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */
-#define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */
-#define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */
-#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
-#define DW_UART_RAR 0xc4 /* Receive Address Register */
-#define DW_UART_TAR 0xc8 /* Transmit Address Register */
-#define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */
-#define DW_UART_CPR 0xf4 /* Component Parameter Register */
-#define DW_UART_UCV 0xf8 /* UART Component Version */
-
-/* Receive / Transmit Address Register bits */
-#define DW_UART_ADDR_MASK GENMASK(7, 0)
-
-/* Line Status Register bits */
-#define DW_UART_LSR_ADDR_RCVD BIT(8)
-
-/* Transceiver Control Register bits */
-#define DW_UART_TCR_RS485_EN BIT(0)
-#define DW_UART_TCR_RE_POL BIT(1)
-#define DW_UART_TCR_DE_POL BIT(2)
-#define DW_UART_TCR_XFER_MODE GENMASK(4, 3)
-#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
-#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
-#define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
-
-/* Line Extended Control Register bits */
-#define DW_UART_LCR_EXT_DLS_E BIT(0)
-#define DW_UART_LCR_EXT_ADDR_MATCH BIT(1)
-#define DW_UART_LCR_EXT_SEND_ADDR BIT(2)
-#define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3)
-
-/* Component Parameter Register bits */
-#define DW_UART_CPR_ABP_DATA_WIDTH GENMASK(1, 0)
-#define DW_UART_CPR_AFCE_MODE BIT(4)
-#define DW_UART_CPR_THRE_MODE BIT(5)
-#define DW_UART_CPR_SIR_MODE BIT(6)
-#define DW_UART_CPR_SIR_LP_MODE BIT(7)
-#define DW_UART_CPR_ADDITIONAL_FEATURES BIT(8)
-#define DW_UART_CPR_FIFO_ACCESS BIT(9)
-#define DW_UART_CPR_FIFO_STAT BIT(10)
-#define DW_UART_CPR_SHADOW BIT(11)
-#define DW_UART_CPR_ENCODED_PARMS BIT(12)
-#define DW_UART_CPR_DMA_EXTRA BIT(13)
-#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16)
-
-/* Helper for FIFO size calculation */
-#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16)
-
/*
* divisor = div(I) + div(F)
* "I" means integer, "F" means fractional
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 7dd2a8e7b780..2f26f9ecacbe 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -1,11 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Synopsys DesignWare 8250 library header file. */
+#ifndef _SERIAL_8250_DWLIB_H_
+#define _SERIAL_8250_DWLIB_H_
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
#include <linux/io.h>
#include <linux/types.h>
#include "8250.h"
+/* Offsets for the DesignWare specific registers */
+#define DW_UART_USR 0x1f /* UART Status Register */
+#define DW_UART_DMASA 0xa8 /* DMA Software Ack */
+#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */
+#define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */
+#define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */
+#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
+#define DW_UART_RAR 0xc4 /* Receive Address Register */
+#define DW_UART_TAR 0xc8 /* Transmit Address Register */
+#define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */
+#define DW_UART_CPR 0xf4 /* Component Parameter Register */
+#define DW_UART_UCV 0xf8 /* UART Component Version */
+
+/* Interrupt ID Register bits */
+#define DW_UART_IIR_IID GENMASK(3, 0)
+
+/* Modem Control Register bits */
+#define DW_UART_MCR_SIRE BIT(6)
+
+/* Line Status Register bits */
+#define DW_UART_LSR_ADDR_RCVD BIT(8)
+
+/* UART Status Register bits */
+#define DW_UART_USR_BUSY BIT(0)
+
+/* Transceiver Control Register bits */
+#define DW_UART_TCR_RS485_EN BIT(0)
+#define DW_UART_TCR_RE_POL BIT(1)
+#define DW_UART_TCR_DE_POL BIT(2)
+#define DW_UART_TCR_XFER_MODE GENMASK(4, 3)
+#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0)
+#define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1)
+#define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2)
+
+/* Receive / Transmit Address Register bits */
+#define DW_UART_ADDR_MASK GENMASK(7, 0)
+
+/* Line Extended Control Register bits */
+#define DW_UART_LCR_EXT_DLS_E BIT(0)
+#define DW_UART_LCR_EXT_ADDR_MATCH BIT(1)
+#define DW_UART_LCR_EXT_SEND_ADDR BIT(2)
+#define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3)
+
+/* Component Parameter Register bits */
+#define DW_UART_CPR_ABP_DATA_WIDTH GENMASK(1, 0)
+#define DW_UART_CPR_AFCE_MODE BIT(4)
+#define DW_UART_CPR_THRE_MODE BIT(5)
+#define DW_UART_CPR_SIR_MODE BIT(6)
+#define DW_UART_CPR_SIR_LP_MODE BIT(7)
+#define DW_UART_CPR_ADDITIONAL_FEATURES BIT(8)
+#define DW_UART_CPR_FIFO_ACCESS BIT(9)
+#define DW_UART_CPR_FIFO_STAT BIT(10)
+#define DW_UART_CPR_SHADOW BIT(11)
+#define DW_UART_CPR_ENCODED_PARMS BIT(12)
+#define DW_UART_CPR_DMA_EXTRA BIT(13)
+#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16)
+
+/* Helper for FIFO size calculation */
+#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16)
+
struct dw8250_port_data {
/* Port properties */
int line;
@@ -38,3 +103,5 @@ static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg)
else
writel(reg, p->membase + offset);
}
+
+#endif /* _SERIAL_8250_DWLIB_H_ */
--
2.34.1
^ permalink raw reply related
* [PATCH v6 4/4] serial: 8250_dw: Use a fixed CPR value for UltraRISC DP1000 UART
From: Jia Wang @ 2026-04-29 9:05 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang
In-Reply-To: <20260429-ultrarisc-serial-v6-0-b2c852e0c4c3@ultrarisc.com>
The UltraRISC DP1000 UART does not provide the standard CPR register used
by 8250_dw to discover port capabilities.
Provide a fixed CPR value for the DP1000-specific compatible so the
driver can configure the port correctly.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 480f82d89856..55e40c10f46a 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -959,6 +959,15 @@ static const struct dw8250_platform_data dw8250_intc10ee = {
.quirks = DW_UART_QUIRK_IER_KICK,
};
+static const struct dw8250_platform_data dw8250_ultrarisc_dp1000_data = {
+ .usr_reg = DW_UART_USR,
+ .cpr_value = FIELD_PREP_CONST(DW_UART_CPR_ABP_DATA_WIDTH, 2) |
+ DW_UART_CPR_THRE_MODE |
+ DW_UART_CPR_DMA_EXTRA |
+ DW_UART_CPR_FIFO_MODE_FROM_SIZE(32),
+ .quirks = DW_UART_QUIRK_CPR_VALUE,
+};
+
static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
@@ -966,6 +975,7 @@ static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
{ .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
{ .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
+ { .compatible = "ultrarisc,dp1000-uart", .data = &dw8250_ultrarisc_dp1000_data },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
--
2.34.1
^ permalink raw reply related
* [PATCH v6 3/4] dt-bindings: serial: snps-dw-apb-uart: Add UltraRISC DP1000 UART
From: Jia Wang @ 2026-04-29 9:05 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang,
Conor Dooley
In-Reply-To: <20260429-ultrarisc-serial-v6-0-b2c852e0c4c3@ultrarisc.com>
UltraRISC DP1000 integrates a Synopsys DesignWare APB UART, but it does
not provide the standard CPR and UCV registers.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index 685c1eceb782..49f51b002879 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -78,6 +78,7 @@ properties:
- starfive,jh7100-hsuart
- starfive,jh7100-uart
- starfive,jh7110-uart
+ - ultrarisc,dp1000-uart
- const: snps,dw-apb-uart
- const: snps,dw-apb-uart
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v5 2/4] serial: 8250_dw: build Renesas RZN1 CPR value from DW_UART_CPR_* definitions
From: Andy Shevchenko @ 2026-04-29 9:05 UTC (permalink / raw)
To: Jia Wang
Cc: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, LKML, linux-serial,
linux-riscv, devicetree
In-Reply-To: <177742420562.3222151.9689419292413018986.b4-reply@b4>
On Wed, Apr 29, 2026 at 08:56:45AM +0800, Jia Wang wrote:
> On 2026-04-28 13:58 +0300, Andy Shevchenko wrote:
> > On Tue, Apr 28, 2026 at 05:07:49PM +0800, Jia Wang wrote:
> > > On 2026-04-28 11:41 +0300, Ilpo Järvinen wrote:
...
> > > Thanks. I tried that approach, but the statement-expression form does
> > > not work in this case because the helper is used in static initializers.
> > > So I'll keep it as a plain expression macro for now, and just rework it
> > > into a cleaner multi-line form.
> >
> > Still you can move FIELD_PREP_CONST() into it.
>
> Right, I'll move FIELD_PREP_CONST() in. By the way, does your Reviewed-by
> still hold?
Not for this patch, as it seems we get too many modifications and discussions
around. Let have a fresh look in v6 (the rest of the patches are okay, please
keep tags there).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v6 0/4] serial: 8250_dw: Add support for UltraRISC DP1000 UART
From: Jia Wang @ 2026-04-29 9:05 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang,
Conor Dooley
This patch series adds support for the UltraRISC DP1000 UART controller.
The series includes four patches. The first two are preparatory cleanups;
the last two add the DP1000 compatible and fixed CPR handling.
The patches have been tested on an UltraRISC DP1000 development board with
Linux v7.1-rc1, verifying basic UART functionality.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
Changes in v6:
- Patch 2:
* Simplify the FIFO size -> CPR FIFO_MODE helper.
- Patch 4:
* Use the updated FIFO helper.
- Link to v5: https://patch.msgid.link/20260428-ultrarisc-serial-v5-0-97de63b1e3eb@ultrarisc.com
Changes in v5:
- Rebased onto Linux v7.1-rc1.
- Patch 1:
* Reorder and document the moved DesignWare register/bit definitions.
- Patch 2:
* Add a FIFO size -> CPR FIFO_MODE helper and use it for RZ/N1.
- Patch 4:
* Use the FIFO_MODE helper for DP1000.
- Link to v4: https://patch.msgid.link/20260424-ultrarisc-serial-v4-0-1765a0b4c4a0@ultrarisc.com
Changes in v4:
- Added two preparatory patches before the original series, shifting patch
numbers (former 1/2 -> now 3/4).
- Patch 1:
* Move all DesignWare UART register/field definitions into 8250_dwlib.h
for shared use with 8250_dw.
- Patch 2:
* Converted the Renesas RZ/N1 CPR magic value to use DW_UART_CPR_* macros
and FIELD_PREP_CONST().
- Patch 4:
* Converted the UltraRISC DP1000 CPR magic value to use
DW_UART_CPR_* macros and FIELD_PREP_CONST() (value unchanged).
- Link to v3: https://patch.msgid.link/20260421-ultrarisc-serial-v3-0-3d7f09c2420e@ultrarisc.com
Changes in v3:
- Rebased on Linux v7.0-rc7.
- Patch 1:
* Removed separate `items` entry for DP1000, merging it into the
existing `enum` to comply with the schema.
* Updated commit message to describe DP1000 UART hardware differences.
- Patch 2:
* Drop the custom quirk for missing CPR register.
* Switch to using DW_UART_QUIRK_CPR_VALUE to provide a fixed CPR value.
- Link to v2: https://patch.msgid.link/20260316-ultrarisc-serial-v2-0-6ab3e7fa891c@ultrarisc.com
Changes in v2:
- Rebased on Linux v7.0-rc4 (previously on v7.0-rc2).
- Reordered patch series: DT binding patch comes before driver changes.
- Updated commit message for DT binding patch.
- Link to v1: https://patch.msgid.link/20260316-ultrarisc-serial-v1-0-c464f3e933a5@ultrarisc.com
---
Jia Wang (4):
serial: 8250_dwlib: move DesignWare register definitions to header
serial: 8250_dw: build Renesas RZN1 CPR value from DW_UART_CPR_* definitions
dt-bindings: serial: snps-dw-apb-uart: Add UltraRISC DP1000 UART
serial: 8250_dw: Use a fixed CPR value for UltraRISC DP1000 UART
.../bindings/serial/snps-dw-apb-uart.yaml | 1 +
drivers/tty/serial/8250/8250_dw.c | 31 +++++----
drivers/tty/serial/8250/8250_dwlib.c | 49 ---------------
drivers/tty/serial/8250/8250_dwlib.h | 73 ++++++++++++++++++++++
4 files changed, 93 insertions(+), 61 deletions(-)
---
base-commit: 3b3bea6d4b9c162f9e555905d96b8c1da67ecd5b
change-id: 20260309-ultrarisc-serial-64ff637edf26
Best regards,
--
Jia Wang <wangjia@ultrarisc.com>
^ permalink raw reply
* [PATCH v6 2/4] serial: 8250_dw: build Renesas RZN1 CPR value from DW_UART_CPR_* definitions
From: Jia Wang @ 2026-04-29 9:05 UTC (permalink / raw)
To: Ilpo Järvinen, Andy Shevchenko, Greg Kroah-Hartman,
Jiri Slaby, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-serial, linux-riscv, devicetree, Jia Wang
In-Reply-To: <20260429-ultrarisc-serial-v6-0-b2c852e0c4c3@ultrarisc.com>
Replace the magic CPR value for Renesas RZ/N1 with a composition using
DW_UART_CPR_* bit/field definitions and FIELD_PREP_CONST().
Introduce a helper macro to convert a FIFO size (bytes) into the CPR
FIFO_MODE field value, with BUILD_BUG_ON_ZERO() checks for alignment and
bounds. Use it to replace the literal FIFO_MODE values in the RZN1.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/tty/serial/8250/8250_dw.c | 10 +++++++++-
drivers/tty/serial/8250/8250_dwlib.h | 8 +++++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 467755bf0092..480f82d89856 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -937,7 +937,15 @@ static const struct dw8250_platform_data dw8250_armada_38x_data = {
static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
.usr_reg = DW_UART_USR,
- .cpr_value = 0x00012f32,
+ .cpr_value = FIELD_PREP_CONST(DW_UART_CPR_ABP_DATA_WIDTH, 2) |
+ DW_UART_CPR_AFCE_MODE |
+ DW_UART_CPR_THRE_MODE |
+ DW_UART_CPR_ADDITIONAL_FEATURES |
+ DW_UART_CPR_FIFO_ACCESS |
+ DW_UART_CPR_FIFO_STAT |
+ DW_UART_CPR_SHADOW |
+ DW_UART_CPR_DMA_EXTRA |
+ DW_UART_CPR_FIFO_MODE_FROM_SIZE(16),
.quirks = DW_UART_QUIRK_CPR_VALUE | DW_UART_QUIRK_IS_DMA_FC,
};
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 2f26f9ecacbe..1fe52332e774 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -6,6 +6,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/build_bug.h>
#include <linux/io.h>
#include <linux/types.h>
@@ -68,8 +69,13 @@
#define DW_UART_CPR_DMA_EXTRA BIT(13)
#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16)
-/* Helper for FIFO size calculation */
+/* Helpers for FIFO size calculation */
#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16)
+#define DW_UART_CPR_FIFO_MODE_FROM_SIZE(size) \
+ (FIELD_PREP_CONST(DW_UART_CPR_FIFO_MODE, \
+ BUILD_BUG_ON_ZERO((size) > 2048) + \
+ BUILD_BUG_ON_ZERO((size) % 16) + \
+ ((size) / 16)))
struct dw8250_port_data {
/* Port properties */
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v5 2/4] serial: 8250_dw: build Renesas RZN1 CPR value from DW_UART_CPR_* definitions
From: Jia Wang @ 2026-04-29 0:56 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Jia Wang, Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, LKML,
linux-serial, linux-riscv, devicetree
In-Reply-To: <afCS7GEG7gtyC7RH@ashevche-desk.local>
On 2026-04-28 13:58 +0300, Andy Shevchenko wrote:
> On Tue, Apr 28, 2026 at 05:07:49PM +0800, Jia Wang wrote:
> > On 2026-04-28 11:41 +0300, Ilpo Järvinen wrote:
> > > On Tue, 28 Apr 2026, Andy Shevchenko wrote:
> > > > On Tue, Apr 28, 2026 at 01:26:27PM +0800, Jia Wang wrote:
>
> ...
>
> > > #define DW_UART_CPR_FIFO_MODE_FROM_SIZE(size) \
> > > ({ \
> > > typeof (size) __size = size; \
> > > \
> > > static_assert(IS_ALIGNED((__size), 16)); \
> > > static_assert(__size <= DW_UART_CPR_FIFO_MODE_MAX); \
> > > \
> > > FIELD_PREP_CONST(DW_UART_CPR_FIFO_MODE, __size / 16); \
> > > })
> >
> > Thanks. I tried that approach, but the statement-expression form does
> > not work in this case because the helper is used in static initializers.
> > So I'll keep it as a plain expression macro for now, and just rework it
> > into a cleaner multi-line form.
>
> Still you can move FIELD_PREP_CONST() into it.
>
Right, I'll move FIELD_PREP_CONST() in. By the way, does your Reviewed-by
still hold?
> --
> With Best Regards,
> Andy Shevchenko
>
>
>
Best Regards,
Jia Wang
^ permalink raw reply
* [PATCH v2 12/15] serial: sc16is7xx: use new UPIO_BUS as iotype
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Now that we have a new UPIO_BUS I/O type, use it to register our serial
port and remove ambiguous membase/iobase workaround.
Note that commit 5da6b1c079e6 ("sc16is7xx: Set iobase to device index")
used the iobase field as an index within the device to allow infering
the order through sysfs, but this is no longer needed since
commit 1ef2c2df1199 ("serial: core: Fix serial core controller port name
to show controller id").
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
This means that displaying iomem_base will now always be zero:
cat /sys/class/tty/ttySC0/iomem_base
0x0
cat /sys/class/tty/ttySC1/iomem_base
0x0
...
But the index can be properly displayed with this instead (example with two
sc16is7xx devices):
$> ls -al /sys/class/tty/ttySC*/device
... /sys/class/tty/ttySC0/device -> ../../../spi1.0:0.0
... /sys/class/tty/ttySC1/device -> ../../../spi1.0:0.1
... /sys/class/tty/ttySC2/device -> ../../../spi3.0:0.0
... /sys/class/tty/ttySC3/device -> ../../../spi3.0:0.1
---
drivers/tty/serial/sc16is7xx.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 1fd64a47341d8263c82fcadd90a4c2e549193e19..4b638e69f36f2d20253d8de31f52ecfe349aa39f 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1472,14 +1472,7 @@ static int sc16is7xx_setup_channel(struct sc16is7xx_one *one, int i,
port->type = PORT_SC16IS7XX;
port->fifosize = SC16IS7XX_FIFO_SIZE;
port->flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
- port->iobase = i;
- /*
- * Use all ones as membase to make sure uart_configure_port() in
- * serial_core.c does not abort for SPI/I2C devices where the
- * membase address is not applicable.
- */
- port->membase = (void __iomem *)~0;
- port->iotype = UPIO_PORT;
+ port->iotype = UPIO_BUS;
port->rs485_config = sc16is7xx_config_rs485;
port->rs485_supported = sc16is7xx_rs485_supported;
port->ops = &sc16is7xx_ops;
--
2.47.3
^ permalink raw reply related
* [PATCH v2 13/15] serial: max310x: use new UPIO_BUS as iotype
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Now that we have a new UPIO_BUS I/O type, use it to register our serial
port and remove obscure membase/iobase workaround.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
drivers/tty/serial/max310x.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index ac7d3f197c3a5ce3531d5607f48e21a807314021..cd0496e307091dae1f53911abf86726f52d5770d 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1380,14 +1380,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
s->p[i].port.type = PORT_MAX310X;
s->p[i].port.fifosize = MAX310X_FIFO_SIZE;
s->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
- s->p[i].port.iotype = UPIO_PORT;
- s->p[i].port.iobase = i;
- /*
- * Use all ones as membase to make sure uart_configure_port() in
- * serial_core.c does not abort for SPI/I2C devices where the
- * membase address is not applicable.
- */
- s->p[i].port.membase = (void __iomem *)~0;
+ s->p[i].port.iotype = UPIO_BUS;
s->p[i].port.uartclk = uartclk;
s->p[i].port.rs485_config = max310x_rs485_config;
s->p[i].port.rs485_supported = max310x_rs485_supported;
--
2.47.3
^ permalink raw reply related
* [PATCH v2 11/15] serial: core: add new I/O type for SPI and I2C bus devices
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
I2C/SPI serial drivers don't use the following struct uart_port variables:
port->membase
port->mapbase
port->iobase
However, they are forced to set membase to a non-zero value so that
uart_configure_port() will succeed because of the following check:
/* If there isn't a port here, don't do anything further. */
if (!port->iobase && !port->mapbase && !port->membase)
return;
Add a new I/O type for SPI and I2C bus devices to remove the need to
implement the kind of above-mentioned ambiguous workarounds to make them
work. Now that UART report functions are using uart_iotype_*() functions,
no more irrelevant I/O information are being printed for UPIO_BUS iotypes.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
With this change, uart_match_port() will always return true for UPIO_BUS
types, and this function is not used by any of the SPI/I2C drivers.
---
drivers/tty/serial/serial_core.c | 11 ++++++-----
include/linux/serial_core.h | 1 +
include/uapi/linux/serial.h | 1 +
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index d0d4dba41fb9ee43403391d9d599abc1d64b48ec..0e015477848504e37afb34c8088957083f1662c7 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2516,11 +2516,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
{
unsigned int flags;
- /*
- * If there isn't a port here, don't do anything further.
- */
- if (!port->iobase && !port->mapbase && !port->membase)
- return;
+ /* If there isn't a port here, don't do anything further. */
+ if (uart_iotype_mmio(port->iotype) || uart_iotype_legacy_io(port->iotype))
+ if (!port->iobase && !port->mapbase && !port->membase)
+ return;
/*
* Now do the auto configuration stuff. Note that config_port
@@ -3216,6 +3215,8 @@ bool uart_match_port(const struct uart_port *port1,
return hub6_match_port(port1, port2);
else if (uart_iotype_mmio(port1->iotype))
return port1->mapbase == port2->mapbase;
+ else if (port1->iotype == UPIO_BUS)
+ return true;
else
return false;
}
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index fc3f5ebe389658c197ffc105ce4ac11cacef59bb..626dd939c53c9f920d71aadd360ec0ea0bacce0d 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -437,6 +437,7 @@ enum uart_iotype {
UPIO_TSI = SERIAL_IO_TSI, /* Tsi108/109 type IO */
UPIO_MEM32BE = SERIAL_IO_MEM32BE, /* 32b big endian */
UPIO_MEM16 = SERIAL_IO_MEM16, /* 16b little endian */
+ UPIO_BUS = SERIAL_IO_BUS, /* Serial bus I/O access (ex: SPI, I2C) */
};
struct uart_port {
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index de9b4733607e6b61b08ff7089ff90070168ff4a2..e6f61538fc2837a264d27942afaaf3f12e743445 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -72,6 +72,7 @@ struct serial_struct {
#define SERIAL_IO_TSI 5
#define SERIAL_IO_MEM32BE 6
#define SERIAL_IO_MEM16 7
+#define SERIAL_IO_BUS 8
#define UART_CLEAR_FIFO 0x01
#define UART_USE_FIFO 0x02
--
2.47.3
^ permalink raw reply related
* [PATCH v2 10/15] serial: 8250_rsa: use uart_iotype_*() to simplify code
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Make use of new functions uart_iotype_mmio() and uart_iotype_legacy_io()
to simplify and improve code readability, as well as avoid some variables
init if the iotype is not valid.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
drivers/tty/serial/8250/8250_rsa.c | 40 ++++++++++++++++++--------------------
1 file changed, 19 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_rsa.c b/drivers/tty/serial/8250/8250_rsa.c
index fff9395948e33be6b08355bace70275b7515b608..010ba5af81a08e737e0198d06d150bbe470e6688 100644
--- a/drivers/tty/serial/8250/8250_rsa.c
+++ b/drivers/tty/serial/8250/8250_rsa.c
@@ -19,35 +19,33 @@ static const struct uart_ops *core_port_base_ops;
static int rsa8250_request_resource(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
- unsigned long start = UART_RSA_BASE << port->regshift;
- unsigned int size = 8 << port->regshift;
+ unsigned long start;
+ unsigned int size;
- switch (port->iotype) {
- case UPIO_HUB6:
- case UPIO_PORT:
- start += port->iobase;
- if (!request_region(start, size, "serial-rsa"))
- return -EBUSY;
- return 0;
- default:
+ if (!uart_iotype_legacy_io(port->iotype))
return -EINVAL;
- }
+
+ start = UART_RSA_BASE << port->regshift;
+ start += port->iobase;
+ size = 8 << port->regshift;
+
+ if (!request_region(start, size, "serial-rsa"))
+ return -EBUSY;
+ return 0;
}
static void rsa8250_release_resource(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
- unsigned long offset = UART_RSA_BASE << port->regshift;
- unsigned int size = 8 << port->regshift;
+ unsigned long offset;
+ unsigned int size;
- switch (port->iotype) {
- case UPIO_HUB6:
- case UPIO_PORT:
- release_region(port->iobase + offset, size);
- break;
- default:
- break;
- }
+ if (!uart_iotype_legacy_io(port->iotype))
+ return;
+
+ offset = UART_RSA_BASE << port->regshift;
+ size = 8 << port->regshift;
+ release_region(port->iobase + offset, size);
}
static void univ8250_config_port(struct uart_port *port, int flags)
--
2.47.3
^ permalink raw reply related
* [PATCH v2 08/15] serial: earlycon: use uart_iotype_*() to simplify code
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Make use of new functions uart_iotype_mmio() and uart_iotype_legacy_io()
to simplify and improve code readability.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
Using uart_iotype_mmio() now includes the case for UPIO_TSI and UPIO_AU,
which fell before this patch in the else clause.
UPIO_TSI is no longer used by any driver, so not an issue.
UPIO_AU, if this is even possible for earlycon, falls into the "MMIO" category
in uart_line_info() and uart_report_port()...
---
drivers/tty/serial/earlycon.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index ab9af37f6cda35ea2e3ea966fdac8ba5c4475cb2..e799feaa14bf1ac7c1a5677cd84490e7c486449b 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -75,19 +75,19 @@ static void __init earlycon_print_info(struct earlycon_device *device)
{
struct console *earlycon = device->con;
struct uart_port *port = &device->port;
+ char address[64] = "";
- if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 ||
- port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE)
- pr_info("%s%d at MMIO%s %pa (options '%s')\n",
- earlycon->name, earlycon->index,
- (port->iotype == UPIO_MEM) ? "" :
- (port->iotype == UPIO_MEM16) ? "16" :
- (port->iotype == UPIO_MEM32) ? "32" : "32be",
- &port->mapbase, device->options);
- else
- pr_info("%s%d at I/O port 0x%lx (options '%s')\n",
- earlycon->name, earlycon->index,
- port->iobase, device->options);
+ if (uart_iotype_mmio(port->iotype))
+ scnprintf(address, sizeof(address), " at MMIO%s %pa",
+ (port->iotype == UPIO_MEM) ? "" :
+ (port->iotype == UPIO_MEM16) ? "16" :
+ (port->iotype == UPIO_MEM32) ? "32" : "32be",
+ &port->mapbase);
+ else if (uart_iotype_legacy_io(port->iotype))
+ scnprintf(address, sizeof(address), " at I/O port 0x%lx", port->iobase);
+
+ pr_info("%s%d%s (options '%s')\n", earlycon->name, earlycon->index,
+ address, device->options);
}
static int __init parse_options(struct earlycon_device *device, char *options)
--
2.47.3
^ permalink raw reply related
* [PATCH v2 07/15] serial: core: use uart_iotype_*() to simplify uart_report_port()
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Make use of new functions uart_iotype_mmio() and uart_iotype_legacy_io()
to simplify and improve code readability. It will also prevent displaying
irrelevant I/O information for future IO types (ex: UPIO_BUS). Use %pa to
display the mapbase pointer, as it is done in earlycon_print_info().
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
On 32-bit cpu:
no changes.
On 64-bit cpu:
before:
1004b800.serial: ttySC0 at MMIO 0x1004b800 (irq = 35, base_baud = 0) is a scif
1004bc00.serial: ttySC1 at MMIO 0x1004bc00 (irq = 40, base_baud = 0) is a scif
after:
1004b800.serial: ttySC0 at MMIO 0x000000001004b800 (irq = 35, base_baud = 0) is a scif
1004bc00.serial: ttySC1 at MMIO 0x000000001004bc00 (irq = 40, base_baud = 0) is a scif
---
drivers/tty/serial/serial_core.c | 32 ++++++++++----------------------
1 file changed, 10 insertions(+), 22 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index e9986f9221f946c9075a8eea7ac28d2ad818f095..d0d4dba41fb9ee43403391d9d599abc1d64b48ec 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2483,31 +2483,19 @@ EXPORT_SYMBOL(uart_resume_port);
static inline void
uart_report_port(struct uart_driver *drv, struct uart_port *port)
{
- char address[64];
+ char address[64] = "";
- switch (port->iotype) {
- case UPIO_PORT:
- scnprintf(address, sizeof(address), "I/O 0x%lx", port->iobase);
- break;
- case UPIO_HUB6:
- scnprintf(address, sizeof(address),
- "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
- break;
- case UPIO_MEM:
- case UPIO_MEM16:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_AU:
- case UPIO_TSI:
- scnprintf(address, sizeof(address),
- "MMIO 0x%llx", (unsigned long long)port->mapbase);
- break;
- default:
- strscpy(address, "*unknown*", sizeof(address));
- break;
+ if (uart_iotype_mmio(port->iotype))
+ scnprintf(address, sizeof(address), " at MMIO %pa", &port->mapbase);
+ else if (uart_iotype_legacy_io(port->iotype)) {
+ if (port->iotype == UPIO_PORT)
+ scnprintf(address, sizeof(address), " at I/O 0x%lx", port->iobase);
+ else if (port->iotype == UPIO_HUB6)
+ scnprintf(address, sizeof(address), " at I/O 0x%lx offset 0x%x",
+ port->iobase, port->hub6);
}
- pr_info("%s%s%s at %s (irq = %u, base_baud = %u) is a %s\n",
+ pr_info("%s%s%s%s (irq = %u, base_baud = %u) is a %s\n",
port->dev ? dev_name(port->dev) : "",
port->dev ? ": " : "",
port->name,
--
2.47.3
^ permalink raw reply related
* [PATCH v2 09/15] serial: 8250: use uart_iotype_*() to simplify code
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Make use of new functions uart_iotype_mmio() and uart_iotype_legacy_io()
to simplify and improve code readability.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
drivers/tty/serial/8250/8250_port.c | 43 ++++++-------------------------------
1 file changed, 7 insertions(+), 36 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index af78cc02f38e719573becd0aea226f7790555a3e..20b7de120b1bab596de22d09fdeff8361afd8b17 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -472,16 +472,10 @@ static void set_io_from_upio(struct uart_port *p)
static void
serial_port_out_sync(struct uart_port *p, int offset, int value)
{
- switch (p->iotype) {
- case UPIO_MEM:
- case UPIO_MEM16:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_AU:
+ if (uart_iotype_mmio(p->iotype)) {
p->serial_out(p, offset, value);
p->serial_in(p, UART_LCR); /* safe, no side-effects */
- break;
- default:
+ } else {
p->serial_out(p, offset, value);
}
}
@@ -2863,13 +2857,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port;
- switch (port->iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_MEM16:
- case UPIO_MEM:
+ if (uart_iotype_mmio(port->iotype)) {
if (!port->mapbase)
return -EINVAL;
@@ -2883,14 +2871,9 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
return -ENOMEM;
}
}
- return 0;
- case UPIO_HUB6:
- case UPIO_PORT:
+ } else if (uart_iotype_legacy_io(port->iotype)) {
if (!request_region(port->iobase, size, "serial"))
return -EBUSY;
- return 0;
- case UPIO_UNKNOWN:
- break;
}
return 0;
@@ -2901,15 +2884,9 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
unsigned int size = serial8250_port_size(up);
struct uart_port *port = &up->port;
- switch (port->iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_MEM16:
- case UPIO_MEM:
+ if (uart_iotype_mmio(port->iotype)) {
if (!port->mapbase)
- break;
+ return;
if (port->flags & UPF_IOREMAP) {
iounmap(port->membase);
@@ -2917,14 +2894,8 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
}
release_mem_region(port->mapbase, size);
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
+ } else if (uart_iotype_legacy_io(port->iotype)) {
release_region(port->iobase, size);
- break;
- case UPIO_UNKNOWN:
- break;
}
}
--
2.47.3
^ permalink raw reply related
* [PATCH v2 06/15] serial: core: fix indentation/alignment
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Fixes the following checkpatch warnings:
CHECK: Alignment should match open parenthesis
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
Without this, the next patch will have a checkpatch warning.
---
drivers/tty/serial/serial_core.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 3c909b8a82135a6245e98a9ae6bb050fc32590cc..e9986f9221f946c9075a8eea7ac28d2ad818f095 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2508,10 +2508,10 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
}
pr_info("%s%s%s at %s (irq = %u, base_baud = %u) is a %s\n",
- port->dev ? dev_name(port->dev) : "",
- port->dev ? ": " : "",
- port->name,
- address, port->irq, port->uartclk / 16, uart_type(port));
+ port->dev ? dev_name(port->dev) : "",
+ port->dev ? ": " : "",
+ port->name,
+ address, port->irq, port->uartclk / 16, uart_type(port));
/* The magic multiplier feature is a bit obscure, so report it too. */
if (port->flags & UPF_MAGIC_MULTIPLIER)
--
2.47.3
^ permalink raw reply related
* [PATCH v2 02/15] serial: core: add uart_iotype_mmio/legacy_io helper functions
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
To help simplify code that check on the io type mode of the port.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
Will also be used by future commit that add UPIO_BUS.
---
drivers/tty/serial/serial_core.c | 28 ++++++++++++++++++++++++++++
include/linux/serial_core.h | 4 ++++
2 files changed, 32 insertions(+)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 7354f8af4853d34e5e819c2887f287970c653b69..c177054f9515e1cb5a1e557c0dac096cb1cbd8cf 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1967,6 +1967,34 @@ static const char *uart_type(struct uart_port *port)
return str;
}
+bool uart_iotype_mmio(enum uart_iotype iotype)
+{
+ switch (iotype) {
+ case UPIO_MEM:
+ case UPIO_MEM32:
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32BE:
+ case UPIO_MEM16:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL_GPL(uart_iotype_mmio);
+
+bool uart_iotype_legacy_io(enum uart_iotype iotype)
+{
+ switch (iotype) {
+ case UPIO_PORT:
+ case UPIO_HUB6:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL_GPL(uart_iotype_legacy_io);
+
#ifdef CONFIG_PROC_FS
static void uart_line_info(struct seq_file *m, struct uart_state *state)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 666430b4789977ae19641442b369eb1c773233f4..fc3f5ebe389658c197ffc105ce4ac11cacef59bb 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -1306,4 +1306,8 @@ static inline int uart_handle_break(struct uart_port *port)
!((cflag) & CLOCAL))
int uart_get_rs485_mode(struct uart_port *port);
+
+bool uart_iotype_mmio(enum uart_iotype iotype);
+bool uart_iotype_legacy_io(enum uart_iotype iotype);
+
#endif /* LINUX_SERIAL_CORE_H */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 03/15] serial: core: use uart_iotype_*() to simplify uart_match_port()
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Make use of new functions uart_iotype_mmio() and uart_iotype_legacy_io()
to simplify and improve code readability.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
drivers/tty/serial/serial_core.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index c177054f9515e1cb5a1e557c0dac096cb1cbd8cf..06a774f93652d65bc8e0f1ed912aa3e5c95e2bfa 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -3222,22 +3222,14 @@ bool uart_match_port(const struct uart_port *port1,
{
if (port1->iotype != port2->iotype)
return false;
-
- switch (port1->iotype) {
- case UPIO_PORT:
+ else if (port1->iotype == UPIO_PORT)
return port1->iobase == port2->iobase;
- case UPIO_HUB6:
+ else if (port1->iotype == UPIO_HUB6)
return hub6_match_port(port1, port2);
- case UPIO_MEM:
- case UPIO_MEM16:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_AU:
- case UPIO_TSI:
+ else if (uart_iotype_mmio(port1->iotype))
return port1->mapbase == port2->mapbase;
- default:
+ else
return false;
- }
}
EXPORT_SYMBOL(uart_match_port);
--
2.47.3
^ permalink raw reply related
* [PATCH v2 01/15] serial: 8250_hub6: add hub6_match_port()
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Move the entire hub6 related match port check into its own function in
8250_hub6.c and add a stub for the case when hub6 code is not even built
into kernel.
Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
drivers/tty/serial/8250/8250.h | 7 +++++++
drivers/tty/serial/8250/8250_hub6.c | 6 ++++++
drivers/tty/serial/serial_core.c | 4 ++--
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 77fe0588fd6bd5c5baac0fa03b7c466742aa9432..9d1068d0489dc4285b1d30489926bd676bcbe60e 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -334,6 +334,13 @@ int fintek_8250_probe(struct uart_8250_port *uart);
static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
#endif
+#ifdef CONFIG_SERIAL_8250_HUB6
+bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
+#else
+static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
+{ return false; }
+#endif
+
#ifdef CONFIG_ARCH_OMAP1
#include <linux/soc/ti/omap1-soc.h>
static inline int is_omap1_8250(struct uart_8250_port *pt)
diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
index 273f59b9bca555e9fb035005d3df2089c5b0a039..eae32c924e29bcaf608d66988aca461b9a53dc91 100644
--- a/drivers/tty/serial/8250/8250_hub6.c
+++ b/drivers/tty/serial/8250/8250_hub6.c
@@ -41,6 +41,12 @@ static struct platform_device hub6_device = {
},
};
+bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
+{
+ return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
+}
+EXPORT_SYMBOL_GPL(hub6_match_port);
+
static int __init hub6_init(void)
{
return platform_device_register(&hub6_device);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 89cebdd278410a5a97f3f5ee1b9c171715145067..7354f8af4853d34e5e819c2887f287970c653b69 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -33,6 +33,7 @@
#include <linux/uaccess.h>
#include "serial_base.h"
+#include "8250/8250.h" /* For hub6_match_port() */
/*
* This is used to lock changes in serial line configuration.
@@ -3198,8 +3199,7 @@ bool uart_match_port(const struct uart_port *port1,
case UPIO_PORT:
return port1->iobase == port2->iobase;
case UPIO_HUB6:
- return port1->iobase == port2->iobase &&
- port1->hub6 == port2->hub6;
+ return hub6_match_port(port1, port2);
case UPIO_MEM:
case UPIO_MEM16:
case UPIO_MEM32:
--
2.47.3
^ permalink raw reply related
* [PATCH v2 15/15] serial: uniformize serial port I/O infos display
From: Hugo Villeneuve @ 2026-04-28 17:54 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Uniformize serial port I/O infos display from three different functions
that display mostly the same information, but with some variations, by
adding a common function.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
Maybe the width information could be dropped entirely?
---
drivers/tty/serial/earlycon.c | 13 +++-------
drivers/tty/serial/serial_core.c | 52 +++++++++++++++++++++++++++-------------
include/linux/serial_core.h | 1 +
3 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index e799feaa14bf1ac7c1a5677cd84490e7c486449b..ce740cdc7cebffca0b4f6be98b8bca66540af72d 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -75,19 +75,12 @@ static void __init earlycon_print_info(struct earlycon_device *device)
{
struct console *earlycon = device->con;
struct uart_port *port = &device->port;
- char address[64] = "";
+ char ioinfos[64];
- if (uart_iotype_mmio(port->iotype))
- scnprintf(address, sizeof(address), " at MMIO%s %pa",
- (port->iotype == UPIO_MEM) ? "" :
- (port->iotype == UPIO_MEM16) ? "16" :
- (port->iotype == UPIO_MEM32) ? "32" : "32be",
- &port->mapbase);
- else if (uart_iotype_legacy_io(port->iotype))
- scnprintf(address, sizeof(address), " at I/O port 0x%lx", port->iobase);
+ uart_get_ioinfos(port, ioinfos, sizeof(ioinfos));
pr_info("%s%d%s (options '%s')\n", earlycon->name, earlycon->index,
- address, device->options);
+ ioinfos, device->options);
}
static int __init parse_options(struct earlycon_device *device, char *options)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0e015477848504e37afb34c8088957083f1662c7..b9a9225d99b616a7f691a8f990fd77ab02609012 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2002,6 +2002,7 @@ static void uart_line_info(struct seq_file *m, struct uart_state *state)
struct tty_port *port = &state->port;
enum uart_pm_state pm_state;
struct uart_port *uport;
+ char ioinfos[64];
char stat_buf[32];
unsigned int status;
@@ -2013,10 +2014,8 @@ static void uart_line_info(struct seq_file *m, struct uart_state *state)
seq_printf(m, "%u: uart:%s", uport->line, uart_type(uport));
- if (uart_iotype_mmio(uport->iotype))
- seq_printf(m, " mmio:%pa", &uport->mapbase);
- else if (uart_iotype_legacy_io(uport->iotype))
- seq_printf(m, " port:%08lX", uport->iobase);
+ uart_get_ioinfos(uport, ioinfos, sizeof(ioinfos));
+ seq_printf(m, "%s", ioinfos);
seq_printf(m, " irq:%u", uport->irq);
@@ -2480,26 +2479,47 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
}
EXPORT_SYMBOL(uart_resume_port);
+static const char *uart_get_mmio_width(struct uart_port *port)
+{
+ switch (port->iotype) {
+ case UPIO_MEM16:
+ return "16";
+ case UPIO_MEM32:
+ case UPIO_MEM32BE:
+ return "32be";
+ case UPIO_AU:
+ case UPIO_MEM:
+ default:
+ return "";
+ }
+}
+
+void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size)
+{
+ buf[0] = '\0';
+
+ if (uart_iotype_mmio(port->iotype)) {
+ scnprintf(buf, size, " MMIO%s:%pa", uart_get_mmio_width(port), &port->mapbase);
+ } else if (uart_iotype_legacy_io(port->iotype)) {
+ if (port->iotype == UPIO_PORT)
+ scnprintf(buf, size, " I/O:0x%lx", port->iobase);
+ else if (port->iotype == UPIO_HUB6)
+ scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
+ }
+}
+EXPORT_SYMBOL(uart_get_ioinfos);
+
static inline void
uart_report_port(struct uart_driver *drv, struct uart_port *port)
{
- char address[64] = "";
+ char ioinfos[64];
- if (uart_iotype_mmio(port->iotype))
- scnprintf(address, sizeof(address), " at MMIO %pa", &port->mapbase);
- else if (uart_iotype_legacy_io(port->iotype)) {
- if (port->iotype == UPIO_PORT)
- scnprintf(address, sizeof(address), " at I/O 0x%lx", port->iobase);
- else if (port->iotype == UPIO_HUB6)
- scnprintf(address, sizeof(address), " at I/O 0x%lx offset 0x%x",
- port->iobase, port->hub6);
- }
+ uart_get_ioinfos(port, ioinfos, sizeof(ioinfos));
pr_info("%s%s%s%s (irq = %u, base_baud = %u) is a %s\n",
port->dev ? dev_name(port->dev) : "",
port->dev ? ": " : "",
- port->name,
- address, port->irq, port->uartclk / 16, uart_type(port));
+ port->name, ioinfos, port->irq, port->uartclk / 16, uart_type(port));
/* The magic multiplier feature is a bit obscure, so report it too. */
if (port->flags & UPF_MAGIC_MULTIPLIER)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 626dd939c53c9f920d71aadd360ec0ea0bacce0d..1289e812b40f3d7b7a02ff1a87eaf649e71e0d2f 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -1308,6 +1308,7 @@ static inline int uart_handle_break(struct uart_port *port)
int uart_get_rs485_mode(struct uart_port *port);
+void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size);
bool uart_iotype_mmio(enum uart_iotype iotype);
bool uart_iotype_legacy_io(enum uart_iotype iotype);
--
2.47.3
^ permalink raw reply related
* [PATCH v2 04/15] serial: core: use uart_iotype_*() to simplify uart_line_info()
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Make use of new functions uart_iotype_mmio() and uart_iotype_legacy_io()
to simplify and improve code readability. This will prevent displaying
irrelevant information for future IO types (ex: UPIO_BUS), while also
addressing the (eventually) invalid check for "iotype >= UPIO_MEM".
This also allows us to remove the confusing cast to (unsigned long long)
for iobase which is defined as an unsigned long, and use %pa to display the
mapbase pointer, as it is done in earlycon_print_info().
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
On 32-bit cpu:
no changes.
On 64-bit cpu:
# cat /proc/tty/driver/sci
before
serinfo:1.0 driver revision:
0: uart:scif mmio:0x1004B800 irq:35 tx:11192 rx:37 RTS|CTS|DTR|DSR|CD
after:
serinfo:1.0 driver revision:
0: uart:scif mmio:0x000000001004b800 irq:35 tx:11339 rx:35 RTS|CTS|DTR|DSR|CD
---
drivers/tty/serial/serial_core.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 06a774f93652d65bc8e0f1ed912aa3e5c95e2bfa..c5ef2dd00a9c9ad57c4010c05daea34fd2053676 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2004,7 +2004,6 @@ static void uart_line_info(struct seq_file *m, struct uart_state *state)
struct uart_port *uport;
char stat_buf[32];
unsigned int status;
- int mmio;
guard(mutex)(&port->mutex);
@@ -2012,13 +2011,14 @@ static void uart_line_info(struct seq_file *m, struct uart_state *state)
if (!uport)
return;
- mmio = uport->iotype >= UPIO_MEM;
- seq_printf(m, "%u: uart:%s %s%08llX irq:%u",
- uport->line, uart_type(uport),
- mmio ? "mmio:0x" : "port:",
- mmio ? (unsigned long long)uport->mapbase
- : (unsigned long long)uport->iobase,
- uport->irq);
+ seq_printf(m, "%u: uart:%s", uport->line, uart_type(uport));
+
+ if (uart_iotype_mmio(uport->iotype))
+ seq_printf(m, " mmio:%pa", &uport->mapbase);
+ else if (uart_iotype_legacy_io(uport->iotype))
+ seq_printf(m, " port:%08lX", uport->iobase);
+
+ seq_printf(m, " irq:%u", uport->irq);
if (uport->type == PORT_UNKNOWN) {
seq_putc(m, '\n');
--
2.47.3
^ permalink raw reply related
* [PATCH v2 05/15] serial: core: replace snprintf with more robust scnprintf
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
In-Reply-To: <20260428-tty-upio-v2-0-01c1857cf761@dimonoff.com>
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Use scnprintf() so we could perhaps one day get rid of snprintf() entirely.
Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
drivers/tty/serial/serial_core.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index c5ef2dd00a9c9ad57c4010c05daea34fd2053676..3c909b8a82135a6245e98a9ae6bb050fc32590cc 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2487,11 +2487,11 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
switch (port->iotype) {
case UPIO_PORT:
- snprintf(address, sizeof(address), "I/O 0x%lx", port->iobase);
+ scnprintf(address, sizeof(address), "I/O 0x%lx", port->iobase);
break;
case UPIO_HUB6:
- snprintf(address, sizeof(address),
- "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
+ scnprintf(address, sizeof(address),
+ "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
break;
case UPIO_MEM:
case UPIO_MEM16:
@@ -2499,8 +2499,8 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
case UPIO_MEM32BE:
case UPIO_AU:
case UPIO_TSI:
- snprintf(address, sizeof(address),
- "MMIO 0x%llx", (unsigned long long)port->mapbase);
+ scnprintf(address, sizeof(address),
+ "MMIO 0x%llx", (unsigned long long)port->mapbase);
break;
default:
strscpy(address, "*unknown*", sizeof(address));
--
2.47.3
^ permalink raw reply related
* [PATCH v2 00/15] serial: add new I/O type for SPI and I2C bus devices
From: Hugo Villeneuve @ 2026-04-28 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: hugo, ilpo.jarvinen, linux-kernel, linux-serial, Hugo Villeneuve
Hello,
this patch series add a new I/O type for serial devices on a SPI/I2C bus,
and a few related cleanups/improvements.
These changes are based on a suggestion [1] made by Ilpo Järvinen during
past sc16is7xx driver patches review.
The first patches make use of uart_iotype_*() functions to simplify and
cleanup the UART report functions.
This cleanup sets the stage to avoid displaying irrelevant MMIO or legacy
I/O information for serial devices on I2C or SPI busses when we add the new
UPIO_BUS type.
The patch "serial: uniformize serial port I/O infos display" is more of an
RFC as an attempt to uniformize the display of I/O informations. If deemed
usefull/appropriate, it can be reworked and integrasted with previous
patches.
Tested on a imx6 board with two SC16is752 using SPI mode, and a dummy
device-tree entry for a MAX3100:
dmesg -t | grep "base_baud"
2020000.serial: ttymxc0 at MMIO 0x2020000 (irq = 197, base_baud = 5000000) is a IMX
21e8000.serial: ttymxc1 at MMIO 0x21e8000 (irq = 198, base_baud = 5000000) is a IMX
spi1.0: ttySC0 (irq = 165, base_baud = 1500000) is a SC16IS752
spi1.0: ttySC1 (irq = 165, base_baud = 1500000) is a SC16IS752
spi3.0: ttySC2 (irq = 37, base_baud = 1500000) is a SC16IS752
spi3.0: ttySC3 (irq = 37, base_baud = 1500000) is a SC16IS752
spi3.1: ttyMAX0 (irq = 0, base_baud = 0) is a MAX3100
Note that before these patches, max3100 silently failed in uart_configure_port()
because membase/iobase/mapbase were zero.
For max310x and SC16is7xx in i2c mode, tested only that driver is properly
registered by using i2c-stub.
Also tested on a custom board with a Renesas RZ/G2L cpu (sh-sci driver) to
confirm there is no regression (also with earlycon):
dmesg -t | grep "MMIO"
earlycon: scif0 at MMIO 0x000000001004b800 (options '115200n8')
1004b800.serial: ttySC0 at MMIO 0x000000001004b800 (irq = 35, base_baud = 0) is a scif
1004bc00.serial: ttySC1 at MMIO 0x000000001004bc00 (irq = 40, base_baud = 0) is a scif
Maybe some of the patches could be merged together, but for now I decided
to keep them separate to help the review process.
Thank you.
[1] https://lore.kernel.org/lkml/2936e18f-44ea-faed-9fa0-2ddefe7c3194@linux.intel.com/raw
Link: [v1] https://lore.kernel.org/all/20260423-tty-upio-v1-0-baf82d3b86d1@dimonoff.com/
Changes for v2:
- Replace snprintf with scnprintf (Ilpo)
- Fix alignment of : to ? (Ilpo)
- Move hub6 match port to 8250_hub6.c (Ilpo)
- earlycon: use uart_iotype_*()
- 8250_rsa: use uart_iotype_*()
- 8250_port: use uart_iotype_*() in serial_port_out_sync()
- simplified uart_line_info() even more and remove intermediate mmio
variable
- Split and rename patch serial: core: prevent irrelevant I/O infos display
for UPIO_BUS to serial: core: use uart_iotype_*() to simplify
uart_report_port() and moved before UPIO_BUS patch.
- Add a new patch to implement a function to uniformize the display
of I/O infos for uart_report_port(), uart_line_info() and
earlycon_print_info(). If accepted could be better integrated/merged with
the next series submission. If not, can simply be dropped.
- Add patch for uart_regiowidth_to_iotype()
---
Hugo Villeneuve (15):
serial: 8250_hub6: add hub6_match_port()
serial: core: add uart_iotype_mmio/legacy_io helper functions
serial: core: use uart_iotype_*() to simplify uart_match_port()
serial: core: use uart_iotype_*() to simplify uart_line_info()
serial: core: replace snprintf with more robust scnprintf
serial: core: fix indentation/alignment
serial: core: use uart_iotype_*() to simplify uart_report_port()
serial: earlycon: use uart_iotype_*() to simplify code
serial: 8250: use uart_iotype_*() to simplify code
serial: 8250_rsa: use uart_iotype_*() to simplify code
serial: core: add new I/O type for SPI and I2C bus devices
serial: sc16is7xx: use new UPIO_BUS as iotype
serial: max310x: use new UPIO_BUS as iotype
serial: max3100: use new UPIO_BUS as iotype
serial: uniformize serial port I/O infos display
drivers/tty/serial/8250/8250.h | 7 ++
drivers/tty/serial/8250/8250_hub6.c | 6 ++
drivers/tty/serial/8250/8250_port.c | 43 ++---------
drivers/tty/serial/8250/8250_rsa.c | 40 +++++------
drivers/tty/serial/earlycon.c | 17 ++---
drivers/tty/serial/max3100.c | 1 +
drivers/tty/serial/max310x.c | 9 +--
drivers/tty/serial/sc16is7xx.c | 9 +--
drivers/tty/serial/serial_core.c | 137 ++++++++++++++++++++++--------------
include/linux/serial_core.h | 6 ++
include/uapi/linux/serial.h | 1 +
11 files changed, 137 insertions(+), 139 deletions(-)
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260428-tty-upio-93a350a4d69a
Best regards,
--
Hugo Villeneuve <hvilleneuve@dimonoff.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox