Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Changhuang Liang <changhuang.liang@starfivetech.com>
To: Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Jonathan Corbet <corbet@lwn.net>, Joel Stanley <joel@jms.id.au>,
	Andrew Jeffery <andrew@codeconstruct.com.au>,
	Chia-Wei Wang <chiawei_wang@aspeedtech.com>,
	Oskar Senft <osk@google.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Changhuang Liang <changhuang.liang@starfivetech.com>,
	Shuah Khan <skhan@linuxfoundation.org>,
	Jani Nikula <jani.nikula@intel.com>,
	Vitaly Lubart <lubvital@gmail.com>,
	Hanjun Guo <guohanjun@huawei.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Alexander Usyskin <alexander.usyskin@intel.com>,
	Jason Gunthorpe <jgg@ziepe.ca>, Breno Leitao <leitao@debian.org>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	James Morse <james.morse@arm.com>,
	Paolo Abeni <pabeni@redhat.com>,
	Stephen Hemminger <stephen@networkplumber.org>,
	Dave Penkler <dpenkler@gmail.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Jonathan Cameron <jic23@kernel.org>,
	Dan Williams <djbw@kernel.org>,
	Mukesh Rathor <mrathor@linux.microsoft.com>,
	Vladimir Oltean <vladimir.oltean@nxp.com>,
	Alexandra Winter <wintera@linux.ibm.com>,
	Julian Braha <julianbraha@gmail.com>,
	Karthikeyan KS <karthiproffesional@gmail.com>,
	Pengpeng Hou <pengpeng@iscas.ac.cn>,
	openbmc@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org
Subject: [PATCH v2 4/4] uart-routing: Add UART Routing driver for StarFive JHB100 SoC
Date: Sat,  5 Sep 2026 03:29:01 -0700	[thread overview]
Message-ID: <20260905102901.126035-5-changhuang.liang@starfivetech.com> (raw)
In-Reply-To: <20260905102901.126035-1-changhuang.liang@starfivetech.com>

Add driver support for JHB100 UART Routing control, allowing runtime
configuration of RX muxes between UART controllers and I/O pins.

A sysfs interface is provided for easy checking and updating of routing
paths.

Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
 .../sysfs-driver-starfive-uart-routing        |  45 ++++
 MAINTAINERS                                   |   8 +
 drivers/uart-routing/Kconfig                  |  13 ++
 drivers/uart-routing/Makefile                 |   1 +
 drivers/uart-routing/starfive-uart-routing.c  | 192 ++++++++++++++++++
 5 files changed, 259 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-starfive-uart-routing
 create mode 100644 drivers/uart-routing/starfive-uart-routing.c

diff --git a/Documentation/ABI/testing/sysfs-driver-starfive-uart-routing b/Documentation/ABI/testing/sysfs-driver-starfive-uart-routing
new file mode 100644
index 000000000000..737afdf428bc
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-starfive-uart-routing
@@ -0,0 +1,45 @@
+What:		/sys/bus/platform/drivers/starfive-uart-routing/\*/uart\*
+Date:		August 2026
+Contact:	Changhuang Liang <changhuang.liang@starfivetech.com>
+Description:	Selects the RX source of the UARTx device.
+
+		When read, each file shows the list of available options with currently
+		selected option marked by brackets "[]". The list of available options
+		depends on the selected file.
+
+		e.g.
+		cat /sys/bus/platform/drivers/starfive-uart-routing/\*.uart-routing/uart1
+		io0 [io1] io2 io3 io4 io5 io6 io7 io8 io9 io10 io11 io12 io13 io14 uart0 uart1
+		uart2 uart3 uart4 uart5 uart6 uart7 uart8 uart9 uart10 uart11 uart12 uart13 uart14
+
+		In this case, UART1 gets its input from IO1 (physical serial port 1).
+
+		To switch the RX source of UART1 to UART2, write the desired source to the file:
+		echo uart2 > /sys/bus/platform/drivers/starfive-uart-routing/*.uart-routing/uart1
+
+		This indicates that UART1 now receives its input from UART2.
+
+Users:		OpenBMC.  Proposed changes should be mailed to
+		openbmc@lists.ozlabs.org
+
+What:		/sys/bus/platform/drivers/starfive-uart-routing/\*/io\*
+Date:		August 2026
+Contact:	Changhuang Liang <changhuang.liang@starfivetech.com>
+Description:	Selects the RX source of IOx serial port. The current selection
+		will be marked by brackets "[]". The list of available options
+		depends on the selected file.
+
+		e.g.
+		cat /sys/bus/platform/drivers/starfive-uart-routing/\*.uart-routing/io9
+		uart0 uart1 uart2 uart3 uart4 uart5 uart6 uart7 uart8 [uart9] uart10 uart11 uart12
+		uart13 uart14 io0 io1 io2 io3 io4 io5 io6 io7 io8 io9 io10 io11 io12 io13 io14
+
+		In this case, IO9 (physical serial port 9) gets its input from UART9.
+
+		To switch the RX source of IO9 to UART10, write the desired source to the file:
+		echo uart10 > /sys/bus/platform/drivers/starfive-uart-routing/*.uart-routing/io9
+
+		This indicates that IO9 now receives its input from UART10.
+
+Users:		OpenBMC.  Proposed changes should be mailed to
+		openbmc@lists.ozlabs.org
diff --git a/MAINTAINERS b/MAINTAINERS
index ad6706c18f37..16c2fa9aff57 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26115,6 +26115,14 @@ M:	Changhuang Liang <changhuang.liang@starfivetech.com>
 S:	Maintained
 F:	Documentation/devicetree/bindings/soc/starfive/starfive,jhb100-syscon.yaml
 
+STARFIVE UART ROUTING DRIVER
+M:	Changhuang Liang <changhuang.liang@starfivetech.com>
+L:	openbmc@lists.ozlabs.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/ABI/testing/sysfs-driver-starfive-uart-routing
+F:	Documentation/devicetree/bindings/uart-routing/starfive,uart-routing.yaml
+F:	drivers/uart-routing/starfive-uart-routing.c
+
 STATIC BRANCH/CALL
 M:	Peter Zijlstra <peterz@infradead.org>
 M:	Josh Poimboeuf <jpoimboe@kernel.org>
diff --git a/drivers/uart-routing/Kconfig b/drivers/uart-routing/Kconfig
index b67c2a6de74c..13b2424d47c7 100644
--- a/drivers/uart-routing/Kconfig
+++ b/drivers/uart-routing/Kconfig
@@ -28,4 +28,17 @@ config ASPEED_UART_ROUTING
 	  If M is selected, the module will be called
 	  aspeed-uart-routing.
 
+config STARFIVE_UART_ROUTING
+	tristate "StarFive uart routing control"
+	depends on ARCH_STARFIVE || COMPILE_TEST
+	select UART_ROUTING
+	select REGMAP_MMIO
+	help
+	  Provides a driver to control the UART routing paths, allowing
+	  users to perform runtime configuration of the RX muxes among
+	  the UART controllers and I/O pins.
+
+	  If M is selected, the module will be called
+	  starfive-uart-routing.
+
 endmenu
diff --git a/drivers/uart-routing/Makefile b/drivers/uart-routing/Makefile
index 226980c639a4..59d9b65c2273 100644
--- a/drivers/uart-routing/Makefile
+++ b/drivers/uart-routing/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_UART_ROUTING)			+= uart-routing.o
 
 obj-$(CONFIG_ASPEED_UART_ROUTING)		+= aspeed-uart-routing.o
+obj-$(CONFIG_STARFIVE_UART_ROUTING)		+= starfive-uart-routing.o
diff --git a/drivers/uart-routing/starfive-uart-routing.c b/drivers/uart-routing/starfive-uart-routing.c
new file mode 100644
index 000000000000..3bd83ca5a258
--- /dev/null
+++ b/drivers/uart-routing/starfive-uart-routing.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * StarFive JHB100 UART Routing driver
+ *
+ * Copyright (C) 2026 StarFive Technology Co., Ltd
+ */
+
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/sysfs.h>
+
+#include "uart-routing.h"
+
+/* One selector register per channel, holding the IO and UART RX mux. */
+#define JHB100_ROUTING_SEL(ch)		((ch) * 0x04)
+#define JHB100_ROUTING_IO_SHIFT		0
+#define JHB100_ROUTING_UART_SHIFT	8
+#define JHB100_ROUTING_MASK		GENMASK(4, 0)
+
+#define JHB100_UART_PORTS		15	/* UART0-UART14 */
+
+#define JHB100_IO_TARGETS						\
+	"io0",  "io1",  "io2",  "io3",  "io4",				\
+	"io5",  "io6",  "io7",  "io8",  "io9",				\
+	"io10", "io11", "io12", "io13", "io14"
+
+#define JHB100_UART_TARGETS						\
+	"uart0",  "uart1",  "uart2",  "uart3",  "uart4",		\
+	"uart5",  "uart6",  "uart7",  "uart8",  "uart9",		\
+	"uart10", "uart11", "uart12", "uart13", "uart14"
+
+/*
+ * The two mux fields of a channel index the same target list, but starting
+ * from a different end of it: field value 0 selects IO0 for the RX mux of a
+ * UART, and UART0 for the RX mux of an IO pin.
+ */
+static const char *const jhb100_uart_rx_options[] = {
+	JHB100_IO_TARGETS,
+	JHB100_UART_TARGETS,
+	NULL,
+};
+
+static const char *const jhb100_io_rx_options[] = {
+	JHB100_UART_TARGETS,
+	JHB100_IO_TARGETS,
+	NULL,
+};
+
+#define JHB100_UART_SELECTOR(_ch)					\
+	UART_ROUTING_SELECTOR(jhb100_uart##_ch##_sel, uart##_ch,	\
+			      JHB100_ROUTING_SEL(_ch),			\
+			      JHB100_ROUTING_UART_SHIFT,		\
+			      JHB100_ROUTING_MASK,			\
+			      jhb100_uart_rx_options)
+
+#define JHB100_IO_SELECTOR(_ch)						\
+	UART_ROUTING_SELECTOR(jhb100_io##_ch##_sel, io##_ch,		\
+			      JHB100_ROUTING_SEL(_ch),			\
+			      JHB100_ROUTING_IO_SHIFT,			\
+			      JHB100_ROUTING_MASK,			\
+			      jhb100_io_rx_options)
+
+/* RX source of UART0-UART14 */
+JHB100_UART_SELECTOR(0);
+JHB100_UART_SELECTOR(1);
+JHB100_UART_SELECTOR(2);
+JHB100_UART_SELECTOR(3);
+JHB100_UART_SELECTOR(4);
+JHB100_UART_SELECTOR(5);
+JHB100_UART_SELECTOR(6);
+JHB100_UART_SELECTOR(7);
+JHB100_UART_SELECTOR(8);
+JHB100_UART_SELECTOR(9);
+JHB100_UART_SELECTOR(10);
+JHB100_UART_SELECTOR(11);
+JHB100_UART_SELECTOR(12);
+JHB100_UART_SELECTOR(13);
+JHB100_UART_SELECTOR(14);
+
+/* RX source of IO0-IO14 */
+JHB100_IO_SELECTOR(0);
+JHB100_IO_SELECTOR(1);
+JHB100_IO_SELECTOR(2);
+JHB100_IO_SELECTOR(3);
+JHB100_IO_SELECTOR(4);
+JHB100_IO_SELECTOR(5);
+JHB100_IO_SELECTOR(6);
+JHB100_IO_SELECTOR(7);
+JHB100_IO_SELECTOR(8);
+JHB100_IO_SELECTOR(9);
+JHB100_IO_SELECTOR(10);
+JHB100_IO_SELECTOR(11);
+JHB100_IO_SELECTOR(12);
+JHB100_IO_SELECTOR(13);
+JHB100_IO_SELECTOR(14);
+
+static struct attribute *jhb100_uart_routing_attrs[] = {
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart0_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart1_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart2_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart3_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart4_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart5_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart6_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart7_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart8_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart9_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart10_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart11_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart12_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart13_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_uart14_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io0_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io1_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io2_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io3_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io4_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io5_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io6_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io7_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io8_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io9_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io10_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io11_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io12_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io13_sel),
+	UART_ROUTING_SELECTOR_ATTR(jhb100_io14_sel),
+	NULL,
+};
+
+static const struct attribute_group jhb100_uart_routing_attr_group = {
+	.attrs = jhb100_uart_routing_attrs,
+};
+
+static const struct regmap_config jhb100_uart_routing_regmap_cfg = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= JHB100_ROUTING_SEL(JHB100_UART_PORTS - 1),
+};
+
+static int starfive_uart_routing_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct reset_control *rst;
+	void __iomem *reg_base;
+	struct regmap *regmap;
+
+	reg_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(reg_base))
+		return dev_err_probe(dev, PTR_ERR(reg_base),
+				     "Unable to map IO resources\n");
+
+	rst = devm_reset_control_get_exclusive_deasserted(dev, NULL);
+	if (IS_ERR(rst))
+		return dev_err_probe(dev, PTR_ERR(rst),
+				     "Unable to get and deassert reset control\n");
+
+	regmap = devm_regmap_init_mmio(dev, reg_base,
+				       &jhb100_uart_routing_regmap_cfg);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap),
+				     "Unable to init regmap\n");
+
+	return devm_uart_routing_register(dev, regmap,
+					  &jhb100_uart_routing_attr_group);
+}
+
+static const struct of_device_id starfive_uart_routing_match[] = {
+	{ .compatible = "starfive,jhb100-uart-routing" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, starfive_uart_routing_match);
+
+static struct platform_driver starfive_uart_routing_driver = {
+	.probe = starfive_uart_routing_probe,
+	.driver	= {
+		.name = "starfive-uart-routing",
+		.of_match_table = starfive_uart_routing_match,
+	},
+};
+
+module_platform_driver(starfive_uart_routing_driver);
+
+MODULE_AUTHOR("Changhuang Liang <changhuang.liang@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive JHB100 UART Routing driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1



      parent reply	other threads:[~2026-09-05 10:44 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-05 10:28 [PATCH v2 0/4] Add support for StarFive JHB100 UART Routing Changhuang Liang
2026-09-05 10:28 ` [PATCH v2 1/4] uart-routing: Add common UART routing framework Changhuang Liang
2026-09-05 12:30   ` Julian Braha
2026-09-05 10:28 ` [PATCH v2 2/4] soc: aspeed: Move UART routing driver to drivers/uart-routing Changhuang Liang
2026-09-05 10:29 ` [PATCH v2 3/4] dt-bindings: uart-routing: Add binding for StarFive JHB100 UART routing Changhuang Liang
2026-09-05 10:29 ` Changhuang Liang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260905102901.126035-5-changhuang.liang@starfivetech.com \
    --to=changhuang.liang@starfivetech.com \
    --cc=akpm@linux-foundation.org \
    --cc=alexander.usyskin@intel.com \
    --cc=andrew@codeconstruct.com.au \
    --cc=chiawei_wang@aspeedtech.com \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=devicetree@vger.kernel.org \
    --cc=djbw@kernel.org \
    --cc=dpenkler@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=guohanjun@huawei.com \
    --cc=james.morse@arm.com \
    --cc=jani.nikula@intel.com \
    --cc=jgg@ziepe.ca \
    --cc=jic23@kernel.org \
    --cc=joel@jms.id.au \
    --cc=julianbraha@gmail.com \
    --cc=karthiproffesional@gmail.com \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=leitao@debian.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-aspeed@lists.ozlabs.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lubvital@gmail.com \
    --cc=mrathor@linux.microsoft.com \
    --cc=openbmc@lists.ozlabs.org \
    --cc=osk@google.com \
    --cc=p.zabel@pengutronix.de \
    --cc=pabeni@redhat.com \
    --cc=pengpeng@iscas.ac.cn \
    --cc=robh@kernel.org \
    --cc=skhan@linuxfoundation.org \
    --cc=stephen@networkplumber.org \
    --cc=vladimir.oltean@nxp.com \
    --cc=wintera@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox