[PATCH 10/20] net: dsa: xilinx: add skeleton driver for TSN switch

Nagadheeraj Rottela <[email protected]>
Newsgroups org.kernel.vger.linux-devicetree,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <[email protected]>
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 <[email protected]>
---
 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 <[email protected]>
 L:	[email protected]
 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 <[email protected]>");
+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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.