[PATCH 10/20] net: dsa: xilinx: add skeleton driver for TSN switch
From: Nagadheeraj Rottela
Date: Fri Aug 07 2026 - 06:51:15 EST
Add a skeleton DSA driver for the three-port switch block of the
AMD/Xilinx TSN Endpoint Ethernet MAC IP. It binds
"xlnx,tsn-switch", maps the switch fabric and two per-MAC register
windows ("switch", "mac1", "mac2"), and registers a dsa_switch with
num_ports = 3. Port 0 is the CPU port, wired internally to the
endpoint MAC. Ports 1 and 2 are the external user ports backed by
MAC1 and MAC2.
At this stage only get_tag_protocol is wired. setup and teardown
are stubs. MDIO, phylink, frame filtering, and PTP follow in
subsequent patches.
Signed-off-by: Nagadheeraj Rottela <nagadheeraj.rottela@xxxxxxx>
---
MAINTAINERS | 1 +
drivers/net/dsa/Kconfig | 2 +
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/xilinx/Kconfig | 11 +++
drivers/net/dsa/xilinx/Makefile | 3 +
drivers/net/dsa/xilinx/xilinx_tsn.c | 126 ++++++++++++++++++++++++++++
drivers/net/dsa/xilinx/xilinx_tsn.h | 31 +++++++
7 files changed, 175 insertions(+)
create mode 100644 drivers/net/dsa/xilinx/Kconfig
create mode 100644 drivers/net/dsa/xilinx/Makefile
create mode 100644 drivers/net/dsa/xilinx/xilinx_tsn.c
create mode 100644 drivers/net/dsa/xilinx/xilinx_tsn.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6fbe83fb3953..0e91cb2a307d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29613,6 +29613,7 @@ M: Srinivas Neeli <srinivas.neeli@xxxxxxx>
L: netdev@xxxxxxxxxxxxxxx
S: Maintained
F: Documentation/devicetree/bindings/net/xlnx,tsn-endpoint-ethernet-mac.yaml
+F: drivers/net/dsa/xilinx/
F: drivers/net/ethernet/xilinx/tsn/
F: net/dsa/tag_xlnx_tsn.c
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 4ab567c5bbaf..1404a77579f1 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -84,6 +84,8 @@ source "drivers/net/dsa/qca/Kconfig"
source "drivers/net/dsa/sja1105/Kconfig"
+source "drivers/net/dsa/xilinx/Kconfig"
+
source "drivers/net/dsa/xrs700x/Kconfig"
source "drivers/net/dsa/realtek/Kconfig"
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index d2975badffc0..75b8449b575e 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -26,4 +26,5 @@ obj-y += ocelot/
obj-y += qca/
obj-y += realtek/
obj-y += sja1105/
+obj-y += xilinx/
obj-y += xrs700x/
diff --git a/drivers/net/dsa/xilinx/Kconfig b/drivers/net/dsa/xilinx/Kconfig
new file mode 100644
index 000000000000..0bd5efe8490b
--- /dev/null
+++ b/drivers/net/dsa/xilinx/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+config NET_DSA_XILINX_TSN
+ tristate "AMD/Xilinx TSN Endpoint Ethernet MAC switch support"
+ depends on OF && HAS_IOMEM
+ depends on NET_DSA
+ select NET_DSA_TAG_XLNX_TSN
+ help
+ This enables DSA switch support for the three-port switch
+ block of the AMD/Xilinx TSN Endpoint Ethernet MAC IP. Port 0
+ is the CPU port, wired internally to the endpoint MAC; ports 1
+ and 2 are external Ethernet ports backed by MAC1 and MAC2.
diff --git a/drivers/net/dsa/xilinx/Makefile b/drivers/net/dsa/xilinx/Makefile
new file mode 100644
index 000000000000..334f0f979276
--- /dev/null
+++ b/drivers/net/dsa/xilinx/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+obj-$(CONFIG_NET_DSA_XILINX_TSN) += xlnx_tsn_dsa.o
+xlnx_tsn_dsa-y := xilinx_tsn.o
diff --git a/drivers/net/dsa/xilinx/xilinx_tsn.c b/drivers/net/dsa/xilinx/xilinx_tsn.c
new file mode 100644
index 000000000000..6b285c528724
--- /dev/null
+++ b/drivers/net/dsa/xilinx/xilinx_tsn.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD/Xilinx TSN Endpoint Ethernet MAC DSA switch driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <net/dsa.h>
+
+#include "xilinx_tsn.h"
+
+static enum dsa_tag_protocol xlnx_tsn_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
+{
+ return DSA_TAG_PROTO_XLNX_TSN;
+}
+
+static int xlnx_tsn_setup(struct dsa_switch *ds)
+{
+ return 0;
+}
+
+static void xlnx_tsn_teardown(struct dsa_switch *ds)
+{
+}
+
+static const struct dsa_switch_ops xlnx_tsn_switch_ops = {
+ .get_tag_protocol = xlnx_tsn_get_tag_protocol,
+ .setup = xlnx_tsn_setup,
+ .teardown = xlnx_tsn_teardown,
+};
+
+static int xlnx_tsn_map_reg(struct platform_device *pdev, const char *name,
+ void __iomem **out)
+{
+ void __iomem *base;
+
+ base = devm_platform_ioremap_resource_byname(pdev, name);
+ if (IS_ERR(base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(base),
+ "failed to map %s reg window\n", name);
+
+ *out = base;
+ return 0;
+}
+
+static int xlnx_tsn_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dsa_switch *ds;
+ struct xlnx_tsn *sw;
+ int ret;
+
+ sw = devm_kzalloc(dev, sizeof(*sw), GFP_KERNEL);
+ if (!sw)
+ return -ENOMEM;
+
+ sw->dev = dev;
+
+ ret = xlnx_tsn_map_reg(pdev, "switch", &sw->sw_base);
+ if (ret)
+ return ret;
+
+ ret = xlnx_tsn_map_reg(pdev, "mac1", &sw->mac_base[XLNX_TSN_PORT_MAC1]);
+ if (ret)
+ return ret;
+
+ ret = xlnx_tsn_map_reg(pdev, "mac2", &sw->mac_base[XLNX_TSN_PORT_MAC2]);
+ if (ret)
+ return ret;
+
+ ds = &sw->ds;
+ ds->dev = dev;
+ ds->num_ports = XLNX_TSN_NUM_PORTS;
+ ds->ops = &xlnx_tsn_switch_ops;
+ ds->priv = sw;
+
+ platform_set_drvdata(pdev, sw);
+
+ return dsa_register_switch(ds);
+}
+
+static void xlnx_tsn_remove(struct platform_device *pdev)
+{
+ struct xlnx_tsn *sw = platform_get_drvdata(pdev);
+
+ if (!sw)
+ return;
+
+ dsa_unregister_switch(&sw->ds);
+}
+
+static void xlnx_tsn_shutdown(struct platform_device *pdev)
+{
+ struct xlnx_tsn *sw = platform_get_drvdata(pdev);
+
+ if (!sw)
+ return;
+
+ dsa_switch_shutdown(&sw->ds);
+ platform_set_drvdata(pdev, NULL);
+}
+
+static const struct of_device_id xlnx_tsn_of_match[] = {
+ { .compatible = "xlnx,tsn-switch" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, xlnx_tsn_of_match);
+
+static struct platform_driver xlnx_tsn_driver = {
+ .driver = {
+ .name = "xlnx-tsn-switch",
+ .of_match_table = xlnx_tsn_of_match,
+ },
+ .probe = xlnx_tsn_probe,
+ .remove = xlnx_tsn_remove,
+ .shutdown = xlnx_tsn_shutdown,
+};
+module_platform_driver(xlnx_tsn_driver);
+
+MODULE_AUTHOR("Nagadheeraj Rottela <nagadheeraj.rottela@xxxxxxx>");
+MODULE_DESCRIPTION("AMD/Xilinx TSN Endpoint Ethernet MAC DSA switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/xilinx/xilinx_tsn.h b/drivers/net/dsa/xilinx/xilinx_tsn.h
new file mode 100644
index 000000000000..0f9af866bd18
--- /dev/null
+++ b/drivers/net/dsa/xilinx/xilinx_tsn.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AMD/Xilinx TSN Endpoint Ethernet MAC DSA switch driver.
+ */
+#ifndef _XILINX_TSN_H
+#define _XILINX_TSN_H
+
+#include <linux/types.h>
+#include <net/dsa.h>
+
+#define XLNX_TSN_NUM_PORTS 3
+#define XLNX_TSN_CPU_PORT 0
+#define XLNX_TSN_PORT_MAC1 1
+#define XLNX_TSN_PORT_MAC2 2
+
+/**
+ * struct xlnx_tsn - per-IP switch state
+ * @ds: DSA switch
+ * @dev: backing device
+ * @sw_base: switch fabric register window
+ * @mac_base: per-MAC register windows, indexed by user-port number
+ * (index 0 unused; MAC1 at [1], MAC2 at [2])
+ */
+struct xlnx_tsn {
+ struct dsa_switch ds;
+ struct device *dev;
+ void __iomem *sw_base;
+ void __iomem *mac_base[XLNX_TSN_NUM_PORTS];
+};
+
+#endif /* _XILINX_TSN_H */
--
2.34.1