[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220922040102.1554459-14-colin.foster@in-advantage.com>
Date: Wed, 21 Sep 2022 21:01:01 -0700
From: Colin Foster <colin.foster@...advantage.com>
To: linux-gpio@...r.kernel.org, linux-kernel@...r.kernel.org,
devicetree@...r.kernel.org, netdev@...r.kernel.org
Cc: Russell King <linux@...linux.org.uk>,
Linus Walleij <linus.walleij@...aro.org>,
UNGLinuxDriver@...rochip.com,
Alexandre Belloni <alexandre.belloni@...tlin.com>,
Claudiu Manoil <claudiu.manoil@....com>,
Lee Jones <lee@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Rob Herring <robh+dt@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Jakub Kicinski <kuba@...nel.org>,
Eric Dumazet <edumazet@...gle.com>,
"David S. Miller" <davem@...emloft.net>,
Vladimir Oltean <olteanv@...il.com>,
Florian Fainelli <f.fainelli@...il.com>,
Vivien Didelot <vivien.didelot@...il.com>,
Andrew Lunn <andrew@...n.ch>
Subject: [PATCH v2 net-next 13/14] net: dsa: ocelot: add external ocelot switch control
Add control of an external VSC7512 chip.
Currently the four copper phy ports are fully functional. Communication to
external phys is also functional, but the SGMII / QSGMII interfaces are
currently non-functional.
Signed-off-by: Colin Foster <colin.foster@...advantage.com>
---
v2
* Add MAINTAINERS update
* Remove phrase "by way of the ocelot-mfd interface" from the commit
message
* Move MFD resource addition to a separate patch
* Update Kconfig help
* Remove "ocelot_ext_reset()" - it is now shared with ocelot_lib
* Remove unnecessary includes
* Remove "_EXT" from OCELOT_EXT_PORT_MODE_SERDES
* Remove _ext from the compatible string
* Remove no-longer-necessary GCB register definitions
v1 from previous RFC:
* Remove unnecessary byteorder and kconfig header includes.
* Create OCELOT_EXT_PORT_MODE_SERDES macro to match vsc9959.
* Utilize readx_poll_timeout for SYS_RESET_CFG_MEM_INIT.
* *_io_res struct arrays have been moved to the MFD files.
* Changes to utilize phylink_generic_validate() have been squashed.
* dev_err_probe() is used in the probe function.
* Make ocelot_ext_switch_of_match static.
* Relocate ocelot_ext_ops structure to be next to vsc7512_info, to
match what was done in other felix drivers.
* Utilize dev_get_regmap() instead of the obsolete
ocelot_init_regmap_from_resource() routine.
---
MAINTAINERS | 1 +
drivers/net/dsa/ocelot/Kconfig | 19 +++
drivers/net/dsa/ocelot/Makefile | 5 +
drivers/net/dsa/ocelot/ocelot_ext.c | 194 ++++++++++++++++++++++++++++
4 files changed, 219 insertions(+)
create mode 100644 drivers/net/dsa/ocelot/ocelot_ext.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 6705fb8bfd3a..56192a218cb5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14751,6 +14751,7 @@ M: Colin Foster <colin.foster@...advantage.com>
S: Supported
F: Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml
F: drivers/mfd/ocelot*
+F: drivers/net/dsa/ocelot/ocelot_ext.c
F: include/linux/mfd/ocelot.h
OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index 08db9cf76818..74a900e16d76 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig
@@ -1,4 +1,23 @@
# SPDX-License-Identifier: GPL-2.0-only
+config NET_DSA_MSCC_OCELOT_EXT
+ tristate "Ocelot External Ethernet switch support"
+ depends on NET_DSA && SPI
+ depends on NET_VENDOR_MICROSEMI
+ select MDIO_MSCC_MIIM
+ select MFD_OCELOT_CORE
+ select MSCC_OCELOT_SWITCH_LIB
+ select NET_DSA_TAG_OCELOT_8021Q
+ select NET_DSA_TAG_OCELOT
+ help
+ This driver supports the VSC7511, VSC7512, VSC7513 and VSC7514 chips
+ when controlled through SPI.
+
+ The Ocelot switch family is a set of multi-port networking chips. All
+ of these chips have the ability to be controlled externally through
+ SPI or PCIe interfaces.
+
+ Say "Y" here to enable external control to these chips.
+
config NET_DSA_MSCC_FELIX
tristate "Ocelot / Felix Ethernet switch support"
depends on NET_DSA && PCI
diff --git a/drivers/net/dsa/ocelot/Makefile b/drivers/net/dsa/ocelot/Makefile
index f6dd131e7491..d7f3f5a4461c 100644
--- a/drivers/net/dsa/ocelot/Makefile
+++ b/drivers/net/dsa/ocelot/Makefile
@@ -1,11 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
+obj-$(CONFIG_NET_DSA_MSCC_OCELOT_EXT) += mscc_ocelot_ext.o
obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o
mscc_felix-objs := \
felix.o \
felix_vsc9959.o
+mscc_ocelot_ext-objs := \
+ felix.o \
+ ocelot_ext.o
+
mscc_seville-objs := \
felix.o \
seville_vsc9953.o
diff --git a/drivers/net/dsa/ocelot/ocelot_ext.c b/drivers/net/dsa/ocelot/ocelot_ext.c
new file mode 100644
index 000000000000..751e8b6a57a0
--- /dev/null
+++ b/drivers/net/dsa/ocelot/ocelot_ext.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2021-2022 Innovative Advantage Inc.
+ */
+
+#include <linux/mfd/ocelot.h>
+#include <linux/phylink.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <soc/mscc/ocelot.h>
+#include <soc/mscc/vsc7514_regs.h>
+#include "felix.h"
+
+#define VSC7512_NUM_PORTS 11
+
+#define OCELOT_PORT_MODE_SERDES (OCELOT_PORT_MODE_SGMII | \
+ OCELOT_PORT_MODE_QSGMII)
+
+static const u32 vsc7512_port_modes[VSC7512_NUM_PORTS] = {
+ OCELOT_PORT_MODE_INTERNAL,
+ OCELOT_PORT_MODE_INTERNAL,
+ OCELOT_PORT_MODE_INTERNAL,
+ OCELOT_PORT_MODE_INTERNAL,
+ OCELOT_PORT_MODE_SERDES,
+ OCELOT_PORT_MODE_SERDES,
+ OCELOT_PORT_MODE_SERDES,
+ OCELOT_PORT_MODE_SERDES,
+ OCELOT_PORT_MODE_SERDES,
+ OCELOT_PORT_MODE_SERDES,
+ OCELOT_PORT_MODE_SGMII,
+ OCELOT_PORT_MODE_SERDES,
+};
+
+static const u32 *vsc7512_regmap[TARGET_MAX] = {
+ [ANA] = vsc7514_ana_regmap,
+ [QS] = vsc7514_qs_regmap,
+ [QSYS] = vsc7514_qsys_regmap,
+ [REW] = vsc7514_rew_regmap,
+ [SYS] = vsc7514_sys_regmap,
+ [S0] = vsc7514_vcap_regmap,
+ [S1] = vsc7514_vcap_regmap,
+ [S2] = vsc7514_vcap_regmap,
+ [PTP] = vsc7514_ptp_regmap,
+ [DEV_GMII] = vsc7514_dev_gmii_regmap,
+};
+
+static void ocelot_ext_phylink_validate(struct ocelot *ocelot, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state)
+{
+ struct felix *felix = ocelot_to_felix(ocelot);
+ struct dsa_switch *ds = felix->ds;
+ struct dsa_port *dp;
+
+ dp = dsa_to_port(ds, port);
+
+ phylink_generic_validate(&dp->pl_config, supported, state);
+}
+
+static struct regmap *ocelot_ext_regmap_init(struct ocelot *ocelot,
+ const char *name)
+{
+ /* In the ocelot-mfd configuration, regmaps are attached to the device
+ * by name alone, so dev_get_regmap will return the requested regmap
+ * without the need to fully define the resource
+ */
+ return dev_get_regmap(ocelot->dev->parent, name);
+}
+
+static const struct ocelot_ops ocelot_ext_ops = {
+ .reset = ocelot_reset,
+ .wm_enc = ocelot_wm_enc,
+ .wm_dec = ocelot_wm_dec,
+ .wm_stat = ocelot_wm_stat,
+ .port_to_netdev = felix_port_to_netdev,
+ .netdev_to_port = felix_netdev_to_port,
+};
+
+static const struct felix_info vsc7512_info = {
+ .target_io_res = vsc7512_target_io_res,
+ .port_io_res = vsc7512_port_io_res,
+ .regfields = vsc7514_regfields,
+ .map = vsc7512_regmap,
+ .ops = &ocelot_ext_ops,
+ .stats_layout = vsc7514_stats_layout,
+ .vcap = vsc7514_vcap_props,
+ .num_mact_rows = 1024,
+ .num_ports = VSC7512_NUM_PORTS,
+ .num_tx_queues = OCELOT_NUM_TC,
+ .phylink_validate = ocelot_ext_phylink_validate,
+ .port_modes = vsc7512_port_modes,
+ .init_regmap = ocelot_ext_regmap_init,
+};
+
+static int ocelot_ext_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dsa_switch *ds;
+ struct ocelot *ocelot;
+ struct felix *felix;
+ int err;
+
+ felix = kzalloc(sizeof(*felix), GFP_KERNEL);
+ if (!felix)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, felix);
+
+ ocelot = &felix->ocelot;
+ ocelot->dev = dev;
+
+ ocelot->num_flooding_pgids = 1;
+
+ felix->info = &vsc7512_info;
+
+ ds = kzalloc(sizeof(*ds), GFP_KERNEL);
+ if (!ds) {
+ err = -ENOMEM;
+ dev_err_probe(dev, err, "Failed to allocate DSA switch\n");
+ goto err_free_felix;
+ }
+
+ ds->dev = dev;
+ ds->num_ports = felix->info->num_ports;
+ ds->num_tx_queues = felix->info->num_tx_queues;
+
+ ds->ops = &felix_switch_ops;
+ ds->priv = ocelot;
+ felix->ds = ds;
+ felix->tag_proto = DSA_TAG_PROTO_OCELOT;
+
+ err = dsa_register_switch(ds);
+ if (err) {
+ dev_err_probe(dev, err, "Failed to register DSA switch\n");
+ goto err_free_ds;
+ }
+
+ return 0;
+
+err_free_ds:
+ kfree(ds);
+err_free_felix:
+ kfree(felix);
+ return err;
+}
+
+static int ocelot_ext_remove(struct platform_device *pdev)
+{
+ struct felix *felix = dev_get_drvdata(&pdev->dev);
+
+ if (!felix)
+ return 0;
+
+ dsa_unregister_switch(felix->ds);
+
+ kfree(felix->ds);
+ kfree(felix);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static void ocelot_ext_shutdown(struct platform_device *pdev)
+{
+ struct felix *felix = dev_get_drvdata(&pdev->dev);
+
+ if (!felix)
+ return;
+
+ dsa_switch_shutdown(felix->ds);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+}
+
+static const struct of_device_id ocelot_ext_switch_of_match[] = {
+ { .compatible = "mscc,vsc7512-switch" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ocelot_ext_switch_of_match);
+
+static struct platform_driver ocelot_ext_switch_driver = {
+ .driver = {
+ .name = "ocelot-switch",
+ .of_match_table = of_match_ptr(ocelot_ext_switch_of_match),
+ },
+ .probe = ocelot_ext_probe,
+ .remove = ocelot_ext_remove,
+ .shutdown = ocelot_ext_shutdown,
+};
+module_platform_driver(ocelot_ext_switch_driver);
+
+MODULE_DESCRIPTION("External Ocelot Switch driver");
+MODULE_LICENSE("GPL");
--
2.25.1
Powered by blists - more mailing lists