linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI
@ 2021-08-14  2:49 Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables Colin Foster
                   ` (9 more replies)
  0 siblings, 10 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Add support for configuration and control of the VSC7511, VSC7512, VSC7513, and
VSC7514 chips over a SPI interface. The intent is to control these chips from an
external CPU. The expectation is to have most of the features of the
net/ethernet/mscc/ocelot_vsc7514 driver.

RFC history:
v1 (accidentally named vN)
	Initial architecture. Not functional
	General concepts laid out

v2
	Near functional. No CPU port communication, but control over all
	external ports
	Cleaned up regmap implementation from v1

v3
	Functional
	Shared MDIO transactions routed through mdio-mscc-miim
	CPU / NPI port enabled by way of vsc7512_enable_npi_port /
	felix->info->enable_npi_port
	NPI port tagging functional - Requires a CPU port driver that supports
	frames of 1520 bytes. Verified with a patch to the cpsw driver



Colin Foster (10):
  net: dsa: ocelot: remove unnecessary pci_bar variables
  net: mdio: mscc-miim: convert to a regmap implementation
  net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect
    mdio access
  net: dsa: ocelot: felix: Remove requirement for PCS in felix devices
  net: dsa: ocelot: felix: add interface for custom regmaps
  net: mscc: ocelot: split register definitions to a separate file
  net: mscc: ocelot: expose ocelot wm functions
  net: mscc: ocelot: felix: add ability to enable a CPU / NPI port
  net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  docs: devicetree: add documentation for the VSC7512 SPI device

 .../devicetree/bindings/net/dsa/ocelot.txt    |   92 ++
 drivers/net/dsa/ocelot/Kconfig                |   14 +
 drivers/net/dsa/ocelot/Makefile               |    7 +
 drivers/net/dsa/ocelot/felix.c                |   11 +-
 drivers/net/dsa/ocelot/felix.h                |    5 +-
 drivers/net/dsa/ocelot/felix_mdio.c           |   52 +
 drivers/net/dsa/ocelot/felix_mdio.h           |   12 +
 drivers/net/dsa/ocelot/felix_vsc9959.c        |   11 +-
 drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c   | 1133 +++++++++++++++++
 drivers/net/dsa/ocelot/seville_vsc9953.c      |  109 +-
 drivers/net/ethernet/mscc/Makefile            |    2 +
 drivers/net/ethernet/mscc/ocelot.c            |    8 +
 drivers/net/ethernet/mscc/ocelot_regs.c       |  309 +++++
 drivers/net/ethernet/mscc/ocelot_vsc7514.c    |  323 +----
 drivers/net/ethernet/mscc/ocelot_wm.c         |   39 +
 drivers/net/mdio/mdio-mscc-miim.c             |  137 +-
 include/linux/mdio/mdio-mscc-miim.h           |   19 +
 include/soc/mscc/ocelot.h                     |   24 +
 include/soc/mscc/ocelot_regs.h                |   20 +
 19 files changed, 1857 insertions(+), 470 deletions(-)
 create mode 100644 drivers/net/dsa/ocelot/felix_mdio.c
 create mode 100644 drivers/net/dsa/ocelot/felix_mdio.h
 create mode 100644 drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c
 create mode 100644 drivers/net/ethernet/mscc/ocelot_regs.c
 create mode 100644 drivers/net/ethernet/mscc/ocelot_wm.c
 create mode 100644 include/linux/mdio/mdio-mscc-miim.h
 create mode 100644 include/soc/mscc/ocelot_regs.h

--
2.25.1


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
@ 2021-08-14  2:49 ` Colin Foster
  2021-08-14 11:07   ` Vladimir Oltean
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation Colin Foster
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

The pci_bar variables for the switch and imdio don't make sense for the
generic felix driver. Moving them to felix_vsc9959 to limit scope and
simplify the felix_info struct.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/felix.h         |  2 --
 drivers/net/dsa/ocelot/felix_vsc9959.c | 11 +++++------
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 4d96cad815d5..47769dd386db 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -20,8 +20,6 @@ struct felix_info {
 	int				num_ports;
 	int				num_tx_queues;
 	struct vcap_props		*vcap;
-	int				switch_pci_bar;
-	int				imdio_pci_bar;
 	const struct ptp_clock_info	*ptp_caps;
 
 	/* Some Ocelot switches are integrated into the SoC without the
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index f966a253d1c7..182ca749c8e2 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1359,8 +1359,6 @@ static const struct felix_info felix_info_vsc9959 = {
 	.num_mact_rows		= 2048,
 	.num_ports		= 6,
 	.num_tx_queues		= OCELOT_NUM_TC,
-	.switch_pci_bar		= 4,
-	.imdio_pci_bar		= 0,
 	.quirk_no_xtr_irq	= true,
 	.ptp_caps		= &vsc9959_ptp_caps,
 	.mdio_bus_alloc		= vsc9959_mdio_bus_alloc,
@@ -1388,6 +1386,9 @@ static irqreturn_t felix_irq_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+#define VSC9959_SWITCH_PCI_BAR 4
+#define VSC9959_IMDIO_PCI_BAR 0
+
 static int felix_pci_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *id)
 {
@@ -1419,10 +1420,8 @@ static int felix_pci_probe(struct pci_dev *pdev,
 	ocelot->dev = &pdev->dev;
 	ocelot->num_flooding_pgids = OCELOT_NUM_TC;
 	felix->info = &felix_info_vsc9959;
-	felix->switch_base = pci_resource_start(pdev,
-						felix->info->switch_pci_bar);
-	felix->imdio_base = pci_resource_start(pdev,
-					       felix->info->imdio_pci_bar);
+	felix->switch_base = pci_resource_start(pdev, VSC9959_SWITCH_PCI_BAR);
+	felix->imdio_base = pci_resource_start(pdev, VSC9959_IMDIO_PCI_BAR);
 
 	pci_set_master(pdev);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables Colin Foster
@ 2021-08-14  2:49 ` Colin Foster
  2021-08-14 11:03   ` Vladimir Oltean
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 03/10] net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect mdio access Colin Foster
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Utilize regmap instead of __iomem to perform indirect mdio access. This
will allow for custom regmaps to be used by way of the mscc_miim_setup
function.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/mdio/mdio-mscc-miim.c | 124 +++++++++++++++++++++---------
 1 file changed, 87 insertions(+), 37 deletions(-)

diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
index b36e5ea04ddf..e1849e25c9ca 100644
--- a/drivers/net/mdio/mdio-mscc-miim.c
+++ b/drivers/net/mdio/mdio-mscc-miim.c
@@ -14,6 +14,7 @@
 #include <linux/of_mdio.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 
 #define MSCC_MIIM_REG_STATUS		0x0
 #define		MSCC_MIIM_STATUS_STAT_PENDING	BIT(2)
@@ -35,37 +36,45 @@
 #define MSCC_PHY_REG_PHY_STATUS	0x4
 
 struct mscc_miim_dev {
-	void __iomem *regs;
-	void __iomem *phy_regs;
+	struct regmap *regs;
+	struct regmap *phy_regs;
 };
 
 /* When high resolution timers aren't built-in: we can't use usleep_range() as
  * we would sleep way too long. Use udelay() instead.
  */
-#define mscc_readl_poll_timeout(addr, val, cond, delay_us, timeout_us)	\
+#define mscc_readx_poll_timeout(op, addr, val, cond, delay_us, timeout_us)	\
 ({									\
 	if (!IS_ENABLED(CONFIG_HIGH_RES_TIMERS))			\
-		readl_poll_timeout_atomic(addr, val, cond, delay_us,	\
+		readx_poll_timeout_atomic(op, addr, val, cond, delay_us,	\
 					  timeout_us);			\
-	readl_poll_timeout(addr, val, cond, delay_us, timeout_us);	\
+	readx_poll_timeout(op, addr, val, cond, delay_us, timeout_us);	\
 })
 
-static int mscc_miim_wait_ready(struct mii_bus *bus)
+static int mscc_miim_status(struct mii_bus *bus)
 {
 	struct mscc_miim_dev *miim = bus->priv;
+	int val;
+
+	regmap_read(miim->regs, MSCC_MIIM_REG_STATUS, &val);
+
+	return val;
+}
+
+static int mscc_miim_wait_ready(struct mii_bus *bus)
+{
 	u32 val;
 
-	return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val,
+	return mscc_readx_poll_timeout(mscc_miim_status, bus, val,
 				       !(val & MSCC_MIIM_STATUS_STAT_BUSY), 50,
 				       10000);
 }
 
 static int mscc_miim_wait_pending(struct mii_bus *bus)
 {
-	struct mscc_miim_dev *miim = bus->priv;
 	u32 val;
 
-	return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val,
+	return mscc_readx_poll_timeout(mscc_miim_status, bus, val,
 				       !(val & MSCC_MIIM_STATUS_STAT_PENDING),
 				       50, 10000);
 }
@@ -80,15 +89,16 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum)
 	if (ret)
 		goto out;
 
-	writel(MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
-	       (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | MSCC_MIIM_CMD_OPR_READ,
-	       miim->regs + MSCC_MIIM_REG_CMD);
+	regmap_write(miim->regs, MSCC_MIIM_REG_CMD, MSCC_MIIM_CMD_VLD |
+		     (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
+		     (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
+		     MSCC_MIIM_CMD_OPR_READ);
 
 	ret = mscc_miim_wait_ready(bus);
 	if (ret)
 		goto out;
 
-	val = readl(miim->regs + MSCC_MIIM_REG_DATA);
+	regmap_read(miim->regs, MSCC_MIIM_REG_DATA, &val);
 	if (val & MSCC_MIIM_DATA_ERROR) {
 		ret = -EIO;
 		goto out;
@@ -109,11 +119,11 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id,
 	if (ret < 0)
 		goto out;
 
-	writel(MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
-	       (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
-	       (value << MSCC_MIIM_CMD_WRDATA_SHIFT) |
-	       MSCC_MIIM_CMD_OPR_WRITE,
-	       miim->regs + MSCC_MIIM_REG_CMD);
+	regmap_write(miim->regs, MSCC_MIIM_REG_CMD, MSCC_MIIM_CMD_VLD |
+		     (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
+		     (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
+		     (value << MSCC_MIIM_CMD_WRDATA_SHIFT) |
+		     MSCC_MIIM_CMD_OPR_WRITE);
 
 out:
 	return ret;
@@ -124,26 +134,26 @@ static int mscc_miim_reset(struct mii_bus *bus)
 	struct mscc_miim_dev *miim = bus->priv;
 
 	if (miim->phy_regs) {
-		writel(0, miim->phy_regs + MSCC_PHY_REG_PHY_CFG);
-		writel(0x1ff, miim->phy_regs + MSCC_PHY_REG_PHY_CFG);
+		regmap_write(miim->phy_regs, MSCC_PHY_REG_PHY_CFG, 0);
+		regmap_write(miim->phy_regs, MSCC_PHY_REG_PHY_CFG, 0x1ff);
 		mdelay(500);
 	}
 
 	return 0;
 }
 
-static int mscc_miim_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct mii_bus *bus;
-	struct mscc_miim_dev *dev;
-	int ret;
+static const struct regmap_config mscc_miim_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+};
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
+static int mscc_miim_setup(struct device *dev, struct mii_bus *bus,
+			   struct regmap *mii_regmap, struct regmap *phy_regmap)
+{
+	struct mscc_miim_dev *miim;
 
-	bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*dev));
+	bus = devm_mdiobus_alloc_size(dev, sizeof(*miim));
 	if (!bus)
 		return -ENOMEM;
 
@@ -151,25 +161,65 @@ static int mscc_miim_probe(struct platform_device *pdev)
 	bus->read = mscc_miim_read;
 	bus->write = mscc_miim_write;
 	bus->reset = mscc_miim_reset;
-	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev));
-	bus->parent = &pdev->dev;
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev));
+	bus->parent = dev;
+
+	miim = bus->priv;
+
+	miim->regs = mii_regmap;
+	miim->phy_regs = phy_regmap;
+
+	return 0;
+}
+
+static int mscc_miim_probe(struct platform_device *pdev)
+{
+	struct regmap *mii_regmap, *phy_regmap;
+	void __iomem *regs, *phy_regs;
+	struct mscc_miim_dev *dev;
+	struct resource *res;
+	struct mii_bus *bus;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
 
 	dev = bus->priv;
-	dev->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->regs)) {
+
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(regs)) {
 		dev_err(&pdev->dev, "Unable to map MIIM registers\n");
-		return PTR_ERR(dev->regs);
+		return PTR_ERR(regs);
+	}
+
+	mii_regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+					   &mscc_miim_regmap_config);
+
+	if (IS_ERR(mii_regmap)) {
+		dev_err(&pdev->dev, "Unable to create MIIM regmap\n");
+		return PTR_ERR(mii_regmap);
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (res) {
-		dev->phy_regs = devm_ioremap_resource(&pdev->dev, res);
-		if (IS_ERR(dev->phy_regs)) {
+		phy_regs = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(phy_regs)) {
 			dev_err(&pdev->dev, "Unable to map internal phy registers\n");
+			return PTR_ERR(phy_regs);
+		}
+
+		phy_regmap = devm_regmap_init_mmio(&pdev->dev, phy_regs,
+						   &mscc_miim_regmap_config);
+
+		if (IS_ERR(phy_regmap)) {
+			dev_err(&pdev->dev, "Unable to create phy register regmap\n");
 			return PTR_ERR(dev->phy_regs);
 		}
 	}
 
+	mscc_miim_setup(&pdev->dev, bus, mii_regmap, phy_regmap);
+
 	ret = of_mdiobus_register(bus, pdev->dev.of_node);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 03/10] net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect mdio access
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation Colin Foster
@ 2021-08-14  2:49 ` Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 04/10] net: dsa: ocelot: felix: Remove requirement for PCS in felix devices Colin Foster
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Switch to a shared MDIO access implementation now provided by
drivers/net/mdio/mdio-mscc-miim.c

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/Kconfig           |   1 +
 drivers/net/dsa/ocelot/Makefile          |   1 +
 drivers/net/dsa/ocelot/felix_mdio.c      |  52 +++++++++++
 drivers/net/dsa/ocelot/felix_mdio.h      |  12 +++
 drivers/net/dsa/ocelot/seville_vsc9953.c | 108 ++---------------------
 drivers/net/mdio/mdio-mscc-miim.c        |  39 +++++---
 include/linux/mdio/mdio-mscc-miim.h      |  19 ++++
 7 files changed, 119 insertions(+), 113 deletions(-)
 create mode 100644 drivers/net/dsa/ocelot/felix_mdio.c
 create mode 100644 drivers/net/dsa/ocelot/felix_mdio.h
 create mode 100644 include/linux/mdio/mdio-mscc-miim.h

diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index 932b6b6fe817..61bcc88ae4c1 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig
@@ -19,6 +19,7 @@ config NET_DSA_MSCC_SEVILLE
 	depends on NET_DSA
 	depends on NET_VENDOR_MICROSEMI
 	depends on HAS_IOMEM
+	select MDIO_MSCC_MIIM
 	select MSCC_OCELOT_SWITCH_LIB
 	select NET_DSA_TAG_OCELOT_8021Q
 	select NET_DSA_TAG_OCELOT
diff --git a/drivers/net/dsa/ocelot/Makefile b/drivers/net/dsa/ocelot/Makefile
index f6dd131e7491..34b9b128efb8 100644
--- a/drivers/net/dsa/ocelot/Makefile
+++ b/drivers/net/dsa/ocelot/Makefile
@@ -8,4 +8,5 @@ mscc_felix-objs := \
 
 mscc_seville-objs := \
 	felix.o \
+	felix_mdio.o \
 	seville_vsc9953.o
diff --git a/drivers/net/dsa/ocelot/felix_mdio.c b/drivers/net/dsa/ocelot/felix_mdio.c
new file mode 100644
index 000000000000..aeb036dedd12
--- /dev/null
+++ b/drivers/net/dsa/ocelot/felix_mdio.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Distributed Switch Architecture VSC9953 driver
+ * Copyright (C) 2020, Maxim Kochetkov <fido_max@inbox.ru>
+ */
+#include <linux/types.h>
+#include <soc/mscc/ocelot.h>
+#include <linux/dsa/ocelot.h>
+#include <linux/mdio/mdio-mscc-miim.h>
+#include "felix.h"
+#include "felix_mdio.h"
+
+int felix_mdio_register(struct ocelot *ocelot)
+{
+	struct felix *felix = ocelot_to_felix(ocelot);
+	struct device *dev = ocelot->dev;
+	int rc;
+
+	/* Needed in order to initialize the bus mutex lock */
+	rc = mdiobus_register(felix->imdio);
+	if (rc < 0) {
+		dev_err(dev, "failed to register MDIO bus\n");
+		felix->imdio = NULL;
+	}
+
+	return rc;
+}
+
+int felix_mdio_bus_alloc(struct ocelot *ocelot)
+{
+	struct felix *felix = ocelot_to_felix(ocelot);
+	struct device *dev = ocelot->dev;
+	struct mii_bus *bus;
+	int err;
+
+	err = mscc_miim_setup(dev, &bus, ocelot->targets[GCB],
+			      ocelot->map[GCB][GCB_MIIM_MII_STATUS & REG_MASK],
+			      ocelot->targets[GCB],
+			      ocelot->map[GCB][GCB_PHY_PHY_CFG & REG_MASK]);
+
+	if (!err)
+		felix->imdio = bus;
+
+	return err;
+}
+
+void felix_mdio_bus_free(struct ocelot *ocelot)
+{
+	struct felix *felix = ocelot_to_felix(ocelot);
+
+	if (felix->imdio)
+		mdiobus_unregister(felix->imdio);
+}
diff --git a/drivers/net/dsa/ocelot/felix_mdio.h b/drivers/net/dsa/ocelot/felix_mdio.h
new file mode 100644
index 000000000000..261e979e6955
--- /dev/null
+++ b/drivers/net/dsa/ocelot/felix_mdio.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/* Shared code for indirect MDIO access for Felix drivers
+ *
+ * Author: Colin Foster <colin.foster@in-advantage.com>
+ * Copyright (C) 2021 Innovative Advantage
+ */
+#include <linux/types.h>
+#include <soc/mscc/ocelot.h>
+
+int felix_mdio_bus_alloc(struct ocelot *ocelot);
+int felix_mdio_register(struct ocelot *ocelot);
+void felix_mdio_bus_free(struct ocelot *ocelot);
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 84f93a874d50..0e06750db264 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -11,13 +11,7 @@
 #include <linux/dsa/ocelot.h>
 #include <linux/iopoll.h>
 #include "felix.h"
-
-#define MSCC_MIIM_CMD_OPR_WRITE			BIT(1)
-#define MSCC_MIIM_CMD_OPR_READ			BIT(2)
-#define MSCC_MIIM_CMD_WRDATA_SHIFT		4
-#define MSCC_MIIM_CMD_REGAD_SHIFT		20
-#define MSCC_MIIM_CMD_PHYAD_SHIFT		25
-#define MSCC_MIIM_CMD_VLD			BIT(31)
+#include "felix_mdio.h"
 
 static const u32 vsc9953_ana_regmap[] = {
 	REG(ANA_ADVLEARN,			0x00b500),
@@ -857,7 +851,6 @@ static struct vcap_props vsc9953_vcap_props[] = {
 #define VSC9953_INIT_TIMEOUT			50000
 #define VSC9953_GCB_RST_SLEEP			100
 #define VSC9953_SYS_RAMINIT_SLEEP		80
-#define VCS9953_MII_TIMEOUT			10000
 
 static int vsc9953_gcb_soft_rst_status(struct ocelot *ocelot)
 {
@@ -877,82 +870,6 @@ static int vsc9953_sys_ram_init_status(struct ocelot *ocelot)
 	return val;
 }
 
-static int vsc9953_gcb_miim_pending_status(struct ocelot *ocelot)
-{
-	int val;
-
-	ocelot_field_read(ocelot, GCB_MIIM_MII_STATUS_PENDING, &val);
-
-	return val;
-}
-
-static int vsc9953_gcb_miim_busy_status(struct ocelot *ocelot)
-{
-	int val;
-
-	ocelot_field_read(ocelot, GCB_MIIM_MII_STATUS_BUSY, &val);
-
-	return val;
-}
-
-static int vsc9953_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
-			      u16 value)
-{
-	struct ocelot *ocelot = bus->priv;
-	int err, cmd, val;
-
-	/* Wait while MIIM controller becomes idle */
-	err = readx_poll_timeout(vsc9953_gcb_miim_pending_status, ocelot,
-				 val, !val, 10, VCS9953_MII_TIMEOUT);
-	if (err) {
-		dev_err(ocelot->dev, "MDIO write: pending timeout\n");
-		goto out;
-	}
-
-	cmd = MSCC_MIIM_CMD_VLD | (phy_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
-	      (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
-	      (value << MSCC_MIIM_CMD_WRDATA_SHIFT) |
-	      MSCC_MIIM_CMD_OPR_WRITE;
-
-	ocelot_write(ocelot, cmd, GCB_MIIM_MII_CMD);
-
-out:
-	return err;
-}
-
-static int vsc9953_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
-{
-	struct ocelot *ocelot = bus->priv;
-	int err, cmd, val;
-
-	/* Wait until MIIM controller becomes idle */
-	err = readx_poll_timeout(vsc9953_gcb_miim_pending_status, ocelot,
-				 val, !val, 10, VCS9953_MII_TIMEOUT);
-	if (err) {
-		dev_err(ocelot->dev, "MDIO read: pending timeout\n");
-		goto out;
-	}
-
-	/* Write the MIIM COMMAND register */
-	cmd = MSCC_MIIM_CMD_VLD | (phy_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
-	      (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | MSCC_MIIM_CMD_OPR_READ;
-
-	ocelot_write(ocelot, cmd, GCB_MIIM_MII_CMD);
-
-	/* Wait while read operation via the MIIM controller is in progress */
-	err = readx_poll_timeout(vsc9953_gcb_miim_busy_status, ocelot,
-				 val, !val, 10, VCS9953_MII_TIMEOUT);
-	if (err) {
-		dev_err(ocelot->dev, "MDIO read: busy timeout\n");
-		goto out;
-	}
-
-	val = ocelot_read(ocelot, GCB_MIIM_MII_DATA);
-
-	err = val & 0xFFFF;
-out:
-	return err;
-}
 
 /* CORE_ENA is in SYS:SYSTEM:RESET_CFG
  * MEM_INIT is in SYS:SYSTEM:RESET_CFG
@@ -1086,7 +1003,6 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
 {
 	struct felix *felix = ocelot_to_felix(ocelot);
 	struct device *dev = ocelot->dev;
-	struct mii_bus *bus;
 	int port;
 	int rc;
 
@@ -1098,26 +1014,18 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
 		return -ENOMEM;
 	}
 
-	bus = devm_mdiobus_alloc(dev);
-	if (!bus)
-		return -ENOMEM;
-
-	bus->name = "VSC9953 internal MDIO bus";
-	bus->read = vsc9953_mdio_read;
-	bus->write = vsc9953_mdio_write;
-	bus->parent = dev;
-	bus->priv = ocelot;
-	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
+	rc = felix_mdio_bus_alloc(ocelot);
+	if (rc < 0) {
+		dev_err(dev, "failed to allocate MDIO bus\n");
+		return rc;
+	}
 
-	/* Needed in order to initialize the bus mutex lock */
-	rc = mdiobus_register(bus);
+	rc = felix_mdio_register(ocelot);
 	if (rc < 0) {
 		dev_err(dev, "failed to register MDIO bus\n");
 		return rc;
 	}
 
-	felix->imdio = bus;
-
 	for (port = 0; port < felix->info->num_ports; port++) {
 		struct ocelot_port *ocelot_port = ocelot->ports[port];
 		int addr = port + 4;
@@ -1162,7 +1070,7 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
 		mdio_device_free(pcs->mdio);
 		lynx_pcs_destroy(pcs);
 	}
-	mdiobus_unregister(felix->imdio);
+	felix_mdio_bus_free(ocelot);
 }
 
 static const struct felix_info seville_info_vsc9953 = {
diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
index e1849e25c9ca..9a1f5ef2409f 100644
--- a/drivers/net/mdio/mdio-mscc-miim.c
+++ b/drivers/net/mdio/mdio-mscc-miim.c
@@ -10,6 +10,7 @@
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
+#include <linux/mdio/mdio-mscc-miim.h>
 #include <linux/module.h>
 #include <linux/of_mdio.h>
 #include <linux/phy.h>
@@ -37,7 +38,9 @@
 
 struct mscc_miim_dev {
 	struct regmap *regs;
+	int mii_status_offset;
 	struct regmap *phy_regs;
+	int phy_reset_offset;
 };
 
 /* When high resolution timers aren't built-in: we can't use usleep_range() as
@@ -56,7 +59,8 @@ static int mscc_miim_status(struct mii_bus *bus)
 	struct mscc_miim_dev *miim = bus->priv;
 	int val;
 
-	regmap_read(miim->regs, MSCC_MIIM_REG_STATUS, &val);
+	regmap_read(miim->regs, MSCC_MIIM_REG_STATUS + miim->mii_status_offset,
+		    &val);
 
 	return val;
 }
@@ -89,8 +93,8 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum)
 	if (ret)
 		goto out;
 
-	regmap_write(miim->regs, MSCC_MIIM_REG_CMD, MSCC_MIIM_CMD_VLD |
-		     (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
+	regmap_write(miim->regs, miim->mii_status_offset + MSCC_MIIM_REG_CMD,
+		     MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
 		     (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
 		     MSCC_MIIM_CMD_OPR_READ);
 
@@ -98,7 +102,8 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum)
 	if (ret)
 		goto out;
 
-	regmap_read(miim->regs, MSCC_MIIM_REG_DATA, &val);
+	regmap_read(miim->regs, miim->mii_status_offset + MSCC_MIIM_REG_DATA,
+		    &val);
 	if (val & MSCC_MIIM_DATA_ERROR) {
 		ret = -EIO;
 		goto out;
@@ -119,8 +124,8 @@ static int mscc_miim_write(struct mii_bus *bus, int mii_id,
 	if (ret < 0)
 		goto out;
 
-	regmap_write(miim->regs, MSCC_MIIM_REG_CMD, MSCC_MIIM_CMD_VLD |
-		     (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
+	regmap_write(miim->regs, miim->mii_status_offset + MSCC_MIIM_REG_CMD,
+		     MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
 		     (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
 		     (value << MSCC_MIIM_CMD_WRDATA_SHIFT) |
 		     MSCC_MIIM_CMD_OPR_WRITE);
@@ -134,8 +139,11 @@ static int mscc_miim_reset(struct mii_bus *bus)
 	struct mscc_miim_dev *miim = bus->priv;
 
 	if (miim->phy_regs) {
-		regmap_write(miim->phy_regs, MSCC_PHY_REG_PHY_CFG, 0);
-		regmap_write(miim->phy_regs, MSCC_PHY_REG_PHY_CFG, 0x1ff);
+		regmap_write(miim->phy_regs,
+			     miim->phy_reset_offset + MSCC_PHY_REG_PHY_CFG, 0);
+		regmap_write(miim->phy_regs,
+			     miim->phy_reset_offset + MSCC_PHY_REG_PHY_CFG,
+			     0x1ff);
 		mdelay(500);
 	}
 
@@ -148,10 +156,12 @@ static const struct regmap_config mscc_miim_regmap_config = {
 	.reg_stride	= 4,
 };
 
-static int mscc_miim_setup(struct device *dev, struct mii_bus *bus,
-			   struct regmap *mii_regmap, struct regmap *phy_regmap)
+int mscc_miim_setup(struct device *dev, struct mii_bus **pbus,
+		    struct regmap *mii_regmap, int status_offset,
+		    struct regmap *phy_regmap, int reset_offset)
 {
 	struct mscc_miim_dev *miim;
+	struct mii_bus *bus;
 
 	bus = devm_mdiobus_alloc_size(dev, sizeof(*miim));
 	if (!bus)
@@ -167,10 +177,15 @@ static int mscc_miim_setup(struct device *dev, struct mii_bus *bus,
 	miim = bus->priv;
 
 	miim->regs = mii_regmap;
+	miim->mii_status_offset = status_offset;
 	miim->phy_regs = phy_regmap;
+	miim->phy_reset_offset = reset_offset;
+
+	*pbus = bus;
 
 	return 0;
 }
+EXPORT_SYMBOL(mscc_miim_setup);
 
 static int mscc_miim_probe(struct platform_device *pdev)
 {
@@ -185,8 +200,6 @@ static int mscc_miim_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENODEV;
 
-	dev = bus->priv;
-
 	regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(regs)) {
 		dev_err(&pdev->dev, "Unable to map MIIM registers\n");
@@ -218,7 +231,7 @@ static int mscc_miim_probe(struct platform_device *pdev)
 		}
 	}
 
-	mscc_miim_setup(&pdev->dev, bus, mii_regmap, phy_regmap);
+	mscc_miim_setup(&pdev->dev, &bus, mii_regmap, 0, phy_regmap, 0);
 
 	ret = of_mdiobus_register(bus, pdev->dev.of_node);
 	if (ret < 0) {
diff --git a/include/linux/mdio/mdio-mscc-miim.h b/include/linux/mdio/mdio-mscc-miim.h
new file mode 100644
index 000000000000..3ceab7b6ffc1
--- /dev/null
+++ b/include/linux/mdio/mdio-mscc-miim.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Driver for the MDIO interface of Microsemi network switches.
+ *
+ * Author: Colin Foster <colin.foster@in-advantage.com>
+ * Copyright (C) 2021 Innovative Advantage
+ */
+#ifndef MDIO_MSCC_MIIM_H
+#define MDIO_MSCC_MIIM_H
+
+#include <linux/device.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+
+int mscc_miim_setup(struct device *device, struct mii_bus **bus,
+		    struct regmap *mii_regmap, int status_offset,
+		    struct regmap *phy_regmap, int reset_offset);
+
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 04/10] net: dsa: ocelot: felix: Remove requirement for PCS in felix devices
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (2 preceding siblings ...)
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 03/10] net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect mdio access Colin Foster
@ 2021-08-14  2:49 ` Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 05/10] net: dsa: ocelot: felix: add interface for custom regmaps Colin Foster
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Existing felix devices all have an initialized pcs array. Future devices
might not, so running a NULL check on the array before dereferencing it
will allow those future drivers to not crash at this point

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/felix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index ce607fbaaa3a..74ae322b2126 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -852,7 +852,7 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
 	struct felix *felix = ocelot_to_felix(ocelot);
 	struct dsa_port *dp = dsa_to_port(ds, port);
 
-	if (felix->pcs[port])
+	if (felix->pcs && felix->pcs[port])
 		phylink_set_pcs(dp->pl, &felix->pcs[port]->pcs);
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 05/10] net: dsa: ocelot: felix: add interface for custom regmaps
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (3 preceding siblings ...)
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 04/10] net: dsa: ocelot: felix: Remove requirement for PCS in felix devices Colin Foster
@ 2021-08-14  2:49 ` Colin Foster
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file Colin Foster
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Add an interface so that non-mmio regmaps can be used

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/felix.c           | 4 ++--
 drivers/net/dsa/ocelot/felix.h           | 2 ++
 drivers/net/dsa/ocelot/felix_vsc9959.c   | 6 +++---
 drivers/net/dsa/ocelot/seville_vsc9953.c | 1 +
 4 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 74ae322b2126..77644deb4a35 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -1124,7 +1124,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 		res.start += felix->switch_base;
 		res.end += felix->switch_base;
 
-		target = ocelot_regmap_init(ocelot, &res);
+		target = felix->info->init_regmap(ocelot, &res);
 		if (IS_ERR(target)) {
 			dev_err(ocelot->dev,
 				"Failed to map device memory space\n");
@@ -1161,7 +1161,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 		res.start += felix->switch_base;
 		res.end += felix->switch_base;
 
-		target = ocelot_regmap_init(ocelot, &res);
+		target = felix->info->init_regmap(ocelot, &res);
 		if (IS_ERR(target)) {
 			dev_err(ocelot->dev,
 				"Failed to map memory space for port %d\n",
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 47769dd386db..25f664ef4947 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -45,6 +45,8 @@ struct felix_info {
 				 enum tc_setup_type type, void *type_data);
 	void	(*port_sched_speed_set)(struct ocelot *ocelot, int port,
 					u32 speed);
+	struct regmap *(*init_regmap)(struct ocelot *ocelot,
+				      struct resource *res);
 };
 
 extern const struct dsa_switch_ops felix_switch_ops;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 182ca749c8e2..a84129d18007 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -17,6 +17,8 @@
 #include "felix.h"
 
 #define VSC9959_TAS_GCL_ENTRY_MAX	63
+#define VSC9959_SWITCH_PCI_BAR		4
+#define VSC9959_IMDIO_PCI_BAR		0
 
 static const u32 vsc9959_ana_regmap[] = {
 	REG(ANA_ADVLEARN,			0x0089a0),
@@ -1367,6 +1369,7 @@ static const struct felix_info felix_info_vsc9959 = {
 	.prevalidate_phy_mode	= vsc9959_prevalidate_phy_mode,
 	.port_setup_tc		= vsc9959_port_setup_tc,
 	.port_sched_speed_set	= vsc9959_sched_speed_set,
+	.init_regmap		= ocelot_regmap_init,
 };
 
 static irqreturn_t felix_irq_handler(int irq, void *data)
@@ -1386,9 +1389,6 @@ static irqreturn_t felix_irq_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-#define VSC9959_SWITCH_PCI_BAR 4
-#define VSC9959_IMDIO_PCI_BAR 0
-
 static int felix_pci_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *id)
 {
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 0e06750db264..540cf5bc9c54 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -1089,6 +1089,7 @@ static const struct felix_info seville_info_vsc9953 = {
 	.mdio_bus_free		= vsc9953_mdio_bus_free,
 	.phylink_validate	= vsc9953_phylink_validate,
 	.prevalidate_phy_mode	= vsc9953_prevalidate_phy_mode,
+	.init_regmap		= ocelot_regmap_init,
 };
 
 static int seville_probe(struct platform_device *pdev)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (4 preceding siblings ...)
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 05/10] net: dsa: ocelot: felix: add interface for custom regmaps Colin Foster
@ 2021-08-14  2:49 ` Colin Foster
  2021-08-14 11:15   ` Vladimir Oltean
  2021-08-14 16:56   ` Alexandre Belloni
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions Colin Foster
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:49 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Moving these to a separate file will allow them to be shared to other
drivers.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/ethernet/mscc/Makefile         |   1 +
 drivers/net/ethernet/mscc/ocelot_regs.c    | 309 +++++++++++++++++++++
 drivers/net/ethernet/mscc/ocelot_vsc7514.c | 295 +-------------------
 include/soc/mscc/ocelot_regs.h             |  20 ++
 4 files changed, 331 insertions(+), 294 deletions(-)
 create mode 100644 drivers/net/ethernet/mscc/ocelot_regs.c
 create mode 100644 include/soc/mscc/ocelot_regs.h

diff --git a/drivers/net/ethernet/mscc/Makefile b/drivers/net/ethernet/mscc/Makefile
index 722c27694b21..d539a231a478 100644
--- a/drivers/net/ethernet/mscc/Makefile
+++ b/drivers/net/ethernet/mscc/Makefile
@@ -7,6 +7,7 @@ mscc_ocelot_switch_lib-y := \
 	ocelot_vcap.o \
 	ocelot_flower.o \
 	ocelot_ptp.o \
+	ocelot_regs.o \
 	ocelot_devlink.o
 mscc_ocelot_switch_lib-$(CONFIG_BRIDGE_MRP) += ocelot_mrp.o
 obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot.o
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
new file mode 100644
index 000000000000..b7ba137a7c90
--- /dev/null
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+#include "ocelot.h"
+
+const u32 ocelot_ana_regmap[] = {
+	REG(ANA_ADVLEARN,				0x009000),
+	REG(ANA_VLANMASK,				0x009004),
+	REG(ANA_PORT_B_DOMAIN,				0x009008),
+	REG(ANA_ANAGEFIL,				0x00900c),
+	REG(ANA_ANEVENTS,				0x009010),
+	REG(ANA_STORMLIMIT_BURST,			0x009014),
+	REG(ANA_STORMLIMIT_CFG,				0x009018),
+	REG(ANA_ISOLATED_PORTS,				0x009028),
+	REG(ANA_COMMUNITY_PORTS,			0x00902c),
+	REG(ANA_AUTOAGE,				0x009030),
+	REG(ANA_MACTOPTIONS,				0x009034),
+	REG(ANA_LEARNDISC,				0x009038),
+	REG(ANA_AGENCTRL,				0x00903c),
+	REG(ANA_MIRRORPORTS,				0x009040),
+	REG(ANA_EMIRRORPORTS,				0x009044),
+	REG(ANA_FLOODING,				0x009048),
+	REG(ANA_FLOODING_IPMC,				0x00904c),
+	REG(ANA_SFLOW_CFG,				0x009050),
+	REG(ANA_PORT_MODE,				0x009080),
+	REG(ANA_PGID_PGID,				0x008c00),
+	REG(ANA_TABLES_ANMOVED,				0x008b30),
+	REG(ANA_TABLES_MACHDATA,			0x008b34),
+	REG(ANA_TABLES_MACLDATA,			0x008b38),
+	REG(ANA_TABLES_MACACCESS,			0x008b3c),
+	REG(ANA_TABLES_MACTINDX,			0x008b40),
+	REG(ANA_TABLES_VLANACCESS,			0x008b44),
+	REG(ANA_TABLES_VLANTIDX,			0x008b48),
+	REG(ANA_TABLES_ISDXACCESS,			0x008b4c),
+	REG(ANA_TABLES_ISDXTIDX,			0x008b50),
+	REG(ANA_TABLES_ENTRYLIM,			0x008b00),
+	REG(ANA_TABLES_PTP_ID_HIGH,			0x008b54),
+	REG(ANA_TABLES_PTP_ID_LOW,			0x008b58),
+	REG(ANA_MSTI_STATE,				0x008e00),
+	REG(ANA_PORT_VLAN_CFG,				0x007000),
+	REG(ANA_PORT_DROP_CFG,				0x007004),
+	REG(ANA_PORT_QOS_CFG,				0x007008),
+	REG(ANA_PORT_VCAP_CFG,				0x00700c),
+	REG(ANA_PORT_VCAP_S1_KEY_CFG,			0x007010),
+	REG(ANA_PORT_VCAP_S2_CFG,			0x00701c),
+	REG(ANA_PORT_PCP_DEI_MAP,			0x007020),
+	REG(ANA_PORT_CPU_FWD_CFG,			0x007060),
+	REG(ANA_PORT_CPU_FWD_BPDU_CFG,			0x007064),
+	REG(ANA_PORT_CPU_FWD_GARP_CFG,			0x007068),
+	REG(ANA_PORT_CPU_FWD_CCM_CFG,			0x00706c),
+	REG(ANA_PORT_PORT_CFG,				0x007070),
+	REG(ANA_PORT_POL_CFG,				0x007074),
+	REG(ANA_PORT_PTP_CFG,				0x007078),
+	REG(ANA_PORT_PTP_DLY1_CFG,			0x00707c),
+	REG(ANA_OAM_UPM_LM_CNT,				0x007c00),
+	REG(ANA_PORT_PTP_DLY2_CFG,			0x007080),
+	REG(ANA_PFC_PFC_CFG,				0x008800),
+	REG(ANA_PFC_PFC_TIMER,				0x008804),
+	REG(ANA_IPT_OAM_MEP_CFG,			0x008000),
+	REG(ANA_IPT_IPT,				0x008004),
+	REG(ANA_PPT_PPT,				0x008ac0),
+	REG(ANA_FID_MAP_FID_MAP,			0x000000),
+	REG(ANA_AGGR_CFG,				0x0090b4),
+	REG(ANA_CPUQ_CFG,				0x0090b8),
+	REG(ANA_CPUQ_CFG2,				0x0090bc),
+	REG(ANA_CPUQ_8021_CFG,				0x0090c0),
+	REG(ANA_DSCP_CFG,				0x009100),
+	REG(ANA_DSCP_REWR_CFG,				0x009200),
+	REG(ANA_VCAP_RNG_TYPE_CFG,			0x009240),
+	REG(ANA_VCAP_RNG_VAL_CFG,			0x009260),
+	REG(ANA_VRAP_CFG,				0x009280),
+	REG(ANA_VRAP_HDR_DATA,				0x009284),
+	REG(ANA_VRAP_HDR_MASK,				0x009288),
+	REG(ANA_DISCARD_CFG,				0x00928c),
+	REG(ANA_FID_CFG,				0x009290),
+	REG(ANA_POL_PIR_CFG,				0x004000),
+	REG(ANA_POL_CIR_CFG,				0x004004),
+	REG(ANA_POL_MODE_CFG,				0x004008),
+	REG(ANA_POL_PIR_STATE,				0x00400c),
+	REG(ANA_POL_CIR_STATE,				0x004010),
+	REG(ANA_POL_STATE,				0x004014),
+	REG(ANA_POL_FLOWC,				0x008b80),
+	REG(ANA_POL_HYST,				0x008bec),
+	REG(ANA_POL_MISC_CFG,				0x008bf0),
+};
+EXPORT_SYMBOL(ocelot_ana_regmap);
+
+const u32 ocelot_qs_regmap[] = {
+	REG(QS_XTR_GRP_CFG,				0x000000),
+	REG(QS_XTR_RD,					0x000008),
+	REG(QS_XTR_FRM_PRUNING,				0x000010),
+	REG(QS_XTR_FLUSH,				0x000018),
+	REG(QS_XTR_DATA_PRESENT,			0x00001c),
+	REG(QS_XTR_CFG,					0x000020),
+	REG(QS_INJ_GRP_CFG,				0x000024),
+	REG(QS_INJ_WR,					0x00002c),
+	REG(QS_INJ_CTRL,				0x000034),
+	REG(QS_INJ_STATUS,				0x00003c),
+	REG(QS_INJ_ERR,					0x000040),
+	REG(QS_INH_DBG,					0x000048),
+};
+EXPORT_SYMBOL(ocelot_qs_regmap);
+
+const u32 ocelot_qsys_regmap[] = {
+	REG(QSYS_PORT_MODE,				0x011200),
+	REG(QSYS_SWITCH_PORT_MODE,			0x011234),
+	REG(QSYS_STAT_CNT_CFG,				0x011264),
+	REG(QSYS_EEE_CFG,				0x011268),
+	REG(QSYS_EEE_THRES,				0x011294),
+	REG(QSYS_IGR_NO_SHARING,			0x011298),
+	REG(QSYS_EGR_NO_SHARING,			0x01129c),
+	REG(QSYS_SW_STATUS,				0x0112a0),
+	REG(QSYS_EXT_CPU_CFG,				0x0112d0),
+	REG(QSYS_PAD_CFG,				0x0112d4),
+	REG(QSYS_CPU_GROUP_MAP,				0x0112d8),
+	REG(QSYS_QMAP,					0x0112dc),
+	REG(QSYS_ISDX_SGRP,				0x011400),
+	REG(QSYS_TIMED_FRAME_ENTRY,			0x014000),
+	REG(QSYS_TFRM_MISC,				0x011310),
+	REG(QSYS_TFRM_PORT_DLY,				0x011314),
+	REG(QSYS_TFRM_TIMER_CFG_1,			0x011318),
+	REG(QSYS_TFRM_TIMER_CFG_2,			0x01131c),
+	REG(QSYS_TFRM_TIMER_CFG_3,			0x011320),
+	REG(QSYS_TFRM_TIMER_CFG_4,			0x011324),
+	REG(QSYS_TFRM_TIMER_CFG_5,			0x011328),
+	REG(QSYS_TFRM_TIMER_CFG_6,			0x01132c),
+	REG(QSYS_TFRM_TIMER_CFG_7,			0x011330),
+	REG(QSYS_TFRM_TIMER_CFG_8,			0x011334),
+	REG(QSYS_RED_PROFILE,				0x011338),
+	REG(QSYS_RES_QOS_MODE,				0x011378),
+	REG(QSYS_RES_CFG,				0x012000),
+	REG(QSYS_RES_STAT,				0x012004),
+	REG(QSYS_EGR_DROP_MODE,				0x01137c),
+	REG(QSYS_EQ_CTRL,				0x011380),
+	REG(QSYS_EVENTS_CORE,				0x011384),
+	REG(QSYS_CIR_CFG,				0x000000),
+	REG(QSYS_EIR_CFG,				0x000004),
+	REG(QSYS_SE_CFG,				0x000008),
+	REG(QSYS_SE_DWRR_CFG,				0x00000c),
+	REG(QSYS_SE_CONNECT,				0x00003c),
+	REG(QSYS_SE_DLB_SENSE,				0x000040),
+	REG(QSYS_CIR_STATE,				0x000044),
+	REG(QSYS_EIR_STATE,				0x000048),
+	REG(QSYS_SE_STATE,				0x00004c),
+	REG(QSYS_HSCH_MISC_CFG,				0x011388),
+};
+EXPORT_SYMBOL(ocelot_qsys_regmap);
+
+const u32 ocelot_rew_regmap[] = {
+	REG(REW_PORT_VLAN_CFG,				0x000000),
+	REG(REW_TAG_CFG,				0x000004),
+	REG(REW_PORT_CFG,				0x000008),
+	REG(REW_DSCP_CFG,				0x00000c),
+	REG(REW_PCP_DEI_QOS_MAP_CFG,			0x000010),
+	REG(REW_PTP_CFG,				0x000050),
+	REG(REW_PTP_DLY1_CFG,				0x000054),
+	REG(REW_DSCP_REMAP_DP1_CFG,			0x000690),
+	REG(REW_DSCP_REMAP_CFG,				0x000790),
+	REG(REW_STAT_CFG,				0x000890),
+	REG(REW_PPT,					0x000680),
+};
+EXPORT_SYMBOL(ocelot_rew_regmap);
+
+const u32 ocelot_sys_regmap[] = {
+	REG(SYS_COUNT_RX_OCTETS,			0x000000),
+	REG(SYS_COUNT_RX_UNICAST,			0x000004),
+	REG(SYS_COUNT_RX_MULTICAST,			0x000008),
+	REG(SYS_COUNT_RX_BROADCAST,			0x00000c),
+	REG(SYS_COUNT_RX_SHORTS,			0x000010),
+	REG(SYS_COUNT_RX_FRAGMENTS,			0x000014),
+	REG(SYS_COUNT_RX_JABBERS,			0x000018),
+	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,		0x00001c),
+	REG(SYS_COUNT_RX_SYM_ERRS,			0x000020),
+	REG(SYS_COUNT_RX_64,				0x000024),
+	REG(SYS_COUNT_RX_65_127,			0x000028),
+	REG(SYS_COUNT_RX_128_255,			0x00002c),
+	REG(SYS_COUNT_RX_256_1023,			0x000030),
+	REG(SYS_COUNT_RX_1024_1526,			0x000034),
+	REG(SYS_COUNT_RX_1527_MAX,			0x000038),
+	REG(SYS_COUNT_RX_PAUSE,				0x00003c),
+	REG(SYS_COUNT_RX_CONTROL,			0x000040),
+	REG(SYS_COUNT_RX_LONGS,				0x000044),
+	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x000048),
+	REG(SYS_COUNT_TX_OCTETS,			0x000100),
+	REG(SYS_COUNT_TX_UNICAST,			0x000104),
+	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
+	REG(SYS_COUNT_TX_BROADCAST,			0x00010c),
+	REG(SYS_COUNT_TX_COLLISION,			0x000110),
+	REG(SYS_COUNT_TX_DROPS,				0x000114),
+	REG(SYS_COUNT_TX_PAUSE,				0x000118),
+	REG(SYS_COUNT_TX_64,				0x00011c),
+	REG(SYS_COUNT_TX_65_127,			0x000120),
+	REG(SYS_COUNT_TX_128_511,			0x000124),
+	REG(SYS_COUNT_TX_512_1023,			0x000128),
+	REG(SYS_COUNT_TX_1024_1526,			0x00012c),
+	REG(SYS_COUNT_TX_1527_MAX,			0x000130),
+	REG(SYS_COUNT_TX_AGING,				0x000170),
+	REG(SYS_RESET_CFG,				0x000508),
+	REG(SYS_CMID,					0x00050c),
+	REG(SYS_VLAN_ETYPE_CFG,				0x000510),
+	REG(SYS_PORT_MODE,				0x000514),
+	REG(SYS_FRONT_PORT_MODE,			0x000548),
+	REG(SYS_FRM_AGING,				0x000574),
+	REG(SYS_STAT_CFG,				0x000578),
+	REG(SYS_SW_STATUS,				0x00057c),
+	REG(SYS_MISC_CFG,				0x0005ac),
+	REG(SYS_REW_MAC_HIGH_CFG,			0x0005b0),
+	REG(SYS_REW_MAC_LOW_CFG,			0x0005dc),
+	REG(SYS_CM_ADDR,				0x000500),
+	REG(SYS_CM_DATA,				0x000504),
+	REG(SYS_PAUSE_CFG,				0x000608),
+	REG(SYS_PAUSE_TOT_CFG,				0x000638),
+	REG(SYS_ATOP,					0x00063c),
+	REG(SYS_ATOP_TOT_CFG,				0x00066c),
+	REG(SYS_MAC_FC_CFG,				0x000670),
+	REG(SYS_MMGT,					0x00069c),
+	REG(SYS_MMGT_FAST,				0x0006a0),
+	REG(SYS_EVENTS_DIF,				0x0006a4),
+	REG(SYS_EVENTS_CORE,				0x0006b4),
+	REG(SYS_CNT,					0x000000),
+	REG(SYS_PTP_STATUS,				0x0006b8),
+	REG(SYS_PTP_TXSTAMP,				0x0006bc),
+	REG(SYS_PTP_NXT,				0x0006c0),
+	REG(SYS_PTP_CFG,				0x0006c4),
+};
+EXPORT_SYMBOL(ocelot_sys_regmap);
+
+const u32 ocelot_vcap_regmap[] = {
+	/* VCAP_CORE_CFG */
+	REG(VCAP_CORE_UPDATE_CTRL,			0x000000),
+	REG(VCAP_CORE_MV_CFG,				0x000004),
+	/* VCAP_CORE_CACHE */
+	REG(VCAP_CACHE_ENTRY_DAT,			0x000008),
+	REG(VCAP_CACHE_MASK_DAT,			0x000108),
+	REG(VCAP_CACHE_ACTION_DAT,			0x000208),
+	REG(VCAP_CACHE_CNT_DAT,				0x000308),
+	REG(VCAP_CACHE_TG_DAT,				0x000388),
+	/* VCAP_CONST */
+	REG(VCAP_CONST_VCAP_VER,			0x000398),
+	REG(VCAP_CONST_ENTRY_WIDTH,			0x00039c),
+	REG(VCAP_CONST_ENTRY_CNT,			0x0003a0),
+	REG(VCAP_CONST_ENTRY_SWCNT,			0x0003a4),
+	REG(VCAP_CONST_ENTRY_TG_WIDTH,			0x0003a8),
+	REG(VCAP_CONST_ACTION_DEF_CNT,			0x0003ac),
+	REG(VCAP_CONST_ACTION_WIDTH,			0x0003b0),
+	REG(VCAP_CONST_CNT_WIDTH,			0x0003b4),
+	REG(VCAP_CONST_CORE_CNT,			0x0003b8),
+	REG(VCAP_CONST_IF_CNT,				0x0003bc),
+};
+EXPORT_SYMBOL(ocelot_vcap_regmap);
+
+const u32 ocelot_ptp_regmap[] = {
+	REG(PTP_PIN_CFG,				0x000000),
+	REG(PTP_PIN_TOD_SEC_MSB,			0x000004),
+	REG(PTP_PIN_TOD_SEC_LSB,			0x000008),
+	REG(PTP_PIN_TOD_NSEC,				0x00000c),
+	REG(PTP_PIN_WF_HIGH_PERIOD,			0x000014),
+	REG(PTP_PIN_WF_LOW_PERIOD,			0x000018),
+	REG(PTP_CFG_MISC,				0x0000a0),
+	REG(PTP_CLK_CFG_ADJ_CFG,			0x0000a4),
+	REG(PTP_CLK_CFG_ADJ_FREQ,			0x0000a8),
+};
+EXPORT_SYMBOL(ocelot_ptp_regmap);
+
+const u32 ocelot_dev_gmii_regmap[] = {
+	REG(DEV_CLOCK_CFG,				0x0),
+	REG(DEV_PORT_MISC,				0x4),
+	REG(DEV_EVENTS,					0x8),
+	REG(DEV_EEE_CFG,				0xc),
+	REG(DEV_RX_PATH_DELAY,				0x10),
+	REG(DEV_TX_PATH_DELAY,				0x14),
+	REG(DEV_PTP_PREDICT_CFG,			0x18),
+	REG(DEV_MAC_ENA_CFG,				0x1c),
+	REG(DEV_MAC_MODE_CFG,				0x20),
+	REG(DEV_MAC_MAXLEN_CFG,				0x24),
+	REG(DEV_MAC_TAGS_CFG,				0x28),
+	REG(DEV_MAC_ADV_CHK_CFG,			0x2c),
+	REG(DEV_MAC_IFG_CFG,				0x30),
+	REG(DEV_MAC_HDX_CFG,				0x34),
+	REG(DEV_MAC_DBG_CFG,				0x38),
+	REG(DEV_MAC_FC_MAC_LOW_CFG,			0x3c),
+	REG(DEV_MAC_FC_MAC_HIGH_CFG,			0x40),
+	REG(DEV_MAC_STICKY,				0x44),
+	REG(PCS1G_CFG,					0x48),
+	REG(PCS1G_MODE_CFG,				0x4c),
+	REG(PCS1G_SD_CFG,				0x50),
+	REG(PCS1G_ANEG_CFG,				0x54),
+	REG(PCS1G_ANEG_NP_CFG,				0x58),
+	REG(PCS1G_LB_CFG,				0x5c),
+	REG(PCS1G_DBG_CFG,				0x60),
+	REG(PCS1G_CDET_CFG,				0x64),
+	REG(PCS1G_ANEG_STATUS,				0x68),
+	REG(PCS1G_ANEG_NP_STATUS,			0x6c),
+	REG(PCS1G_LINK_STATUS,				0x70),
+	REG(PCS1G_LINK_DOWN_CNT,			0x74),
+	REG(PCS1G_STICKY,				0x78),
+	REG(PCS1G_DEBUG_STATUS,				0x7c),
+	REG(PCS1G_LPI_CFG,				0x80),
+	REG(PCS1G_LPI_WAKE_ERROR_CNT,			0x84),
+	REG(PCS1G_LPI_STATUS,				0x88),
+	REG(PCS1G_TSTPAT_MODE_CFG,			0x8c),
+	REG(PCS1G_TSTPAT_STATUS,			0x90),
+	REG(DEV_PCS_FX100_CFG,				0x94),
+	REG(DEV_PCS_FX100_STATUS,			0x98),
+};
+EXPORT_SYMBOL(ocelot_dev_gmii_regmap);
diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
index 4bd7e9d9ec61..ef1bf24f51b5 100644
--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
@@ -16,303 +16,10 @@
 #include <net/switchdev.h>
 
 #include <soc/mscc/ocelot_vcap.h>
+#include <soc/mscc/ocelot_regs.h>
 #include <soc/mscc/ocelot_hsio.h>
 #include "ocelot.h"
 
-static const u32 ocelot_ana_regmap[] = {
-	REG(ANA_ADVLEARN,				0x009000),
-	REG(ANA_VLANMASK,				0x009004),
-	REG(ANA_PORT_B_DOMAIN,				0x009008),
-	REG(ANA_ANAGEFIL,				0x00900c),
-	REG(ANA_ANEVENTS,				0x009010),
-	REG(ANA_STORMLIMIT_BURST,			0x009014),
-	REG(ANA_STORMLIMIT_CFG,				0x009018),
-	REG(ANA_ISOLATED_PORTS,				0x009028),
-	REG(ANA_COMMUNITY_PORTS,			0x00902c),
-	REG(ANA_AUTOAGE,				0x009030),
-	REG(ANA_MACTOPTIONS,				0x009034),
-	REG(ANA_LEARNDISC,				0x009038),
-	REG(ANA_AGENCTRL,				0x00903c),
-	REG(ANA_MIRRORPORTS,				0x009040),
-	REG(ANA_EMIRRORPORTS,				0x009044),
-	REG(ANA_FLOODING,				0x009048),
-	REG(ANA_FLOODING_IPMC,				0x00904c),
-	REG(ANA_SFLOW_CFG,				0x009050),
-	REG(ANA_PORT_MODE,				0x009080),
-	REG(ANA_PGID_PGID,				0x008c00),
-	REG(ANA_TABLES_ANMOVED,				0x008b30),
-	REG(ANA_TABLES_MACHDATA,			0x008b34),
-	REG(ANA_TABLES_MACLDATA,			0x008b38),
-	REG(ANA_TABLES_MACACCESS,			0x008b3c),
-	REG(ANA_TABLES_MACTINDX,			0x008b40),
-	REG(ANA_TABLES_VLANACCESS,			0x008b44),
-	REG(ANA_TABLES_VLANTIDX,			0x008b48),
-	REG(ANA_TABLES_ISDXACCESS,			0x008b4c),
-	REG(ANA_TABLES_ISDXTIDX,			0x008b50),
-	REG(ANA_TABLES_ENTRYLIM,			0x008b00),
-	REG(ANA_TABLES_PTP_ID_HIGH,			0x008b54),
-	REG(ANA_TABLES_PTP_ID_LOW,			0x008b58),
-	REG(ANA_MSTI_STATE,				0x008e00),
-	REG(ANA_PORT_VLAN_CFG,				0x007000),
-	REG(ANA_PORT_DROP_CFG,				0x007004),
-	REG(ANA_PORT_QOS_CFG,				0x007008),
-	REG(ANA_PORT_VCAP_CFG,				0x00700c),
-	REG(ANA_PORT_VCAP_S1_KEY_CFG,			0x007010),
-	REG(ANA_PORT_VCAP_S2_CFG,			0x00701c),
-	REG(ANA_PORT_PCP_DEI_MAP,			0x007020),
-	REG(ANA_PORT_CPU_FWD_CFG,			0x007060),
-	REG(ANA_PORT_CPU_FWD_BPDU_CFG,			0x007064),
-	REG(ANA_PORT_CPU_FWD_GARP_CFG,			0x007068),
-	REG(ANA_PORT_CPU_FWD_CCM_CFG,			0x00706c),
-	REG(ANA_PORT_PORT_CFG,				0x007070),
-	REG(ANA_PORT_POL_CFG,				0x007074),
-	REG(ANA_PORT_PTP_CFG,				0x007078),
-	REG(ANA_PORT_PTP_DLY1_CFG,			0x00707c),
-	REG(ANA_OAM_UPM_LM_CNT,				0x007c00),
-	REG(ANA_PORT_PTP_DLY2_CFG,			0x007080),
-	REG(ANA_PFC_PFC_CFG,				0x008800),
-	REG(ANA_PFC_PFC_TIMER,				0x008804),
-	REG(ANA_IPT_OAM_MEP_CFG,			0x008000),
-	REG(ANA_IPT_IPT,				0x008004),
-	REG(ANA_PPT_PPT,				0x008ac0),
-	REG(ANA_FID_MAP_FID_MAP,			0x000000),
-	REG(ANA_AGGR_CFG,				0x0090b4),
-	REG(ANA_CPUQ_CFG,				0x0090b8),
-	REG(ANA_CPUQ_CFG2,				0x0090bc),
-	REG(ANA_CPUQ_8021_CFG,				0x0090c0),
-	REG(ANA_DSCP_CFG,				0x009100),
-	REG(ANA_DSCP_REWR_CFG,				0x009200),
-	REG(ANA_VCAP_RNG_TYPE_CFG,			0x009240),
-	REG(ANA_VCAP_RNG_VAL_CFG,			0x009260),
-	REG(ANA_VRAP_CFG,				0x009280),
-	REG(ANA_VRAP_HDR_DATA,				0x009284),
-	REG(ANA_VRAP_HDR_MASK,				0x009288),
-	REG(ANA_DISCARD_CFG,				0x00928c),
-	REG(ANA_FID_CFG,				0x009290),
-	REG(ANA_POL_PIR_CFG,				0x004000),
-	REG(ANA_POL_CIR_CFG,				0x004004),
-	REG(ANA_POL_MODE_CFG,				0x004008),
-	REG(ANA_POL_PIR_STATE,				0x00400c),
-	REG(ANA_POL_CIR_STATE,				0x004010),
-	REG(ANA_POL_STATE,				0x004014),
-	REG(ANA_POL_FLOWC,				0x008b80),
-	REG(ANA_POL_HYST,				0x008bec),
-	REG(ANA_POL_MISC_CFG,				0x008bf0),
-};
-
-static const u32 ocelot_qs_regmap[] = {
-	REG(QS_XTR_GRP_CFG,				0x000000),
-	REG(QS_XTR_RD,					0x000008),
-	REG(QS_XTR_FRM_PRUNING,				0x000010),
-	REG(QS_XTR_FLUSH,				0x000018),
-	REG(QS_XTR_DATA_PRESENT,			0x00001c),
-	REG(QS_XTR_CFG,					0x000020),
-	REG(QS_INJ_GRP_CFG,				0x000024),
-	REG(QS_INJ_WR,					0x00002c),
-	REG(QS_INJ_CTRL,				0x000034),
-	REG(QS_INJ_STATUS,				0x00003c),
-	REG(QS_INJ_ERR,					0x000040),
-	REG(QS_INH_DBG,					0x000048),
-};
-
-static const u32 ocelot_qsys_regmap[] = {
-	REG(QSYS_PORT_MODE,				0x011200),
-	REG(QSYS_SWITCH_PORT_MODE,			0x011234),
-	REG(QSYS_STAT_CNT_CFG,				0x011264),
-	REG(QSYS_EEE_CFG,				0x011268),
-	REG(QSYS_EEE_THRES,				0x011294),
-	REG(QSYS_IGR_NO_SHARING,			0x011298),
-	REG(QSYS_EGR_NO_SHARING,			0x01129c),
-	REG(QSYS_SW_STATUS,				0x0112a0),
-	REG(QSYS_EXT_CPU_CFG,				0x0112d0),
-	REG(QSYS_PAD_CFG,				0x0112d4),
-	REG(QSYS_CPU_GROUP_MAP,				0x0112d8),
-	REG(QSYS_QMAP,					0x0112dc),
-	REG(QSYS_ISDX_SGRP,				0x011400),
-	REG(QSYS_TIMED_FRAME_ENTRY,			0x014000),
-	REG(QSYS_TFRM_MISC,				0x011310),
-	REG(QSYS_TFRM_PORT_DLY,				0x011314),
-	REG(QSYS_TFRM_TIMER_CFG_1,			0x011318),
-	REG(QSYS_TFRM_TIMER_CFG_2,			0x01131c),
-	REG(QSYS_TFRM_TIMER_CFG_3,			0x011320),
-	REG(QSYS_TFRM_TIMER_CFG_4,			0x011324),
-	REG(QSYS_TFRM_TIMER_CFG_5,			0x011328),
-	REG(QSYS_TFRM_TIMER_CFG_6,			0x01132c),
-	REG(QSYS_TFRM_TIMER_CFG_7,			0x011330),
-	REG(QSYS_TFRM_TIMER_CFG_8,			0x011334),
-	REG(QSYS_RED_PROFILE,				0x011338),
-	REG(QSYS_RES_QOS_MODE,				0x011378),
-	REG(QSYS_RES_CFG,				0x012000),
-	REG(QSYS_RES_STAT,				0x012004),
-	REG(QSYS_EGR_DROP_MODE,				0x01137c),
-	REG(QSYS_EQ_CTRL,				0x011380),
-	REG(QSYS_EVENTS_CORE,				0x011384),
-	REG(QSYS_CIR_CFG,				0x000000),
-	REG(QSYS_EIR_CFG,				0x000004),
-	REG(QSYS_SE_CFG,				0x000008),
-	REG(QSYS_SE_DWRR_CFG,				0x00000c),
-	REG(QSYS_SE_CONNECT,				0x00003c),
-	REG(QSYS_SE_DLB_SENSE,				0x000040),
-	REG(QSYS_CIR_STATE,				0x000044),
-	REG(QSYS_EIR_STATE,				0x000048),
-	REG(QSYS_SE_STATE,				0x00004c),
-	REG(QSYS_HSCH_MISC_CFG,				0x011388),
-};
-
-static const u32 ocelot_rew_regmap[] = {
-	REG(REW_PORT_VLAN_CFG,				0x000000),
-	REG(REW_TAG_CFG,				0x000004),
-	REG(REW_PORT_CFG,				0x000008),
-	REG(REW_DSCP_CFG,				0x00000c),
-	REG(REW_PCP_DEI_QOS_MAP_CFG,			0x000010),
-	REG(REW_PTP_CFG,				0x000050),
-	REG(REW_PTP_DLY1_CFG,				0x000054),
-	REG(REW_DSCP_REMAP_DP1_CFG,			0x000690),
-	REG(REW_DSCP_REMAP_CFG,				0x000790),
-	REG(REW_STAT_CFG,				0x000890),
-	REG(REW_PPT,					0x000680),
-};
-
-static const u32 ocelot_sys_regmap[] = {
-	REG(SYS_COUNT_RX_OCTETS,			0x000000),
-	REG(SYS_COUNT_RX_UNICAST,			0x000004),
-	REG(SYS_COUNT_RX_MULTICAST,			0x000008),
-	REG(SYS_COUNT_RX_BROADCAST,			0x00000c),
-	REG(SYS_COUNT_RX_SHORTS,			0x000010),
-	REG(SYS_COUNT_RX_FRAGMENTS,			0x000014),
-	REG(SYS_COUNT_RX_JABBERS,			0x000018),
-	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,		0x00001c),
-	REG(SYS_COUNT_RX_SYM_ERRS,			0x000020),
-	REG(SYS_COUNT_RX_64,				0x000024),
-	REG(SYS_COUNT_RX_65_127,			0x000028),
-	REG(SYS_COUNT_RX_128_255,			0x00002c),
-	REG(SYS_COUNT_RX_256_1023,			0x000030),
-	REG(SYS_COUNT_RX_1024_1526,			0x000034),
-	REG(SYS_COUNT_RX_1527_MAX,			0x000038),
-	REG(SYS_COUNT_RX_PAUSE,				0x00003c),
-	REG(SYS_COUNT_RX_CONTROL,			0x000040),
-	REG(SYS_COUNT_RX_LONGS,				0x000044),
-	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x000048),
-	REG(SYS_COUNT_TX_OCTETS,			0x000100),
-	REG(SYS_COUNT_TX_UNICAST,			0x000104),
-	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
-	REG(SYS_COUNT_TX_BROADCAST,			0x00010c),
-	REG(SYS_COUNT_TX_COLLISION,			0x000110),
-	REG(SYS_COUNT_TX_DROPS,				0x000114),
-	REG(SYS_COUNT_TX_PAUSE,				0x000118),
-	REG(SYS_COUNT_TX_64,				0x00011c),
-	REG(SYS_COUNT_TX_65_127,			0x000120),
-	REG(SYS_COUNT_TX_128_511,			0x000124),
-	REG(SYS_COUNT_TX_512_1023,			0x000128),
-	REG(SYS_COUNT_TX_1024_1526,			0x00012c),
-	REG(SYS_COUNT_TX_1527_MAX,			0x000130),
-	REG(SYS_COUNT_TX_AGING,				0x000170),
-	REG(SYS_RESET_CFG,				0x000508),
-	REG(SYS_CMID,					0x00050c),
-	REG(SYS_VLAN_ETYPE_CFG,				0x000510),
-	REG(SYS_PORT_MODE,				0x000514),
-	REG(SYS_FRONT_PORT_MODE,			0x000548),
-	REG(SYS_FRM_AGING,				0x000574),
-	REG(SYS_STAT_CFG,				0x000578),
-	REG(SYS_SW_STATUS,				0x00057c),
-	REG(SYS_MISC_CFG,				0x0005ac),
-	REG(SYS_REW_MAC_HIGH_CFG,			0x0005b0),
-	REG(SYS_REW_MAC_LOW_CFG,			0x0005dc),
-	REG(SYS_CM_ADDR,				0x000500),
-	REG(SYS_CM_DATA,				0x000504),
-	REG(SYS_PAUSE_CFG,				0x000608),
-	REG(SYS_PAUSE_TOT_CFG,				0x000638),
-	REG(SYS_ATOP,					0x00063c),
-	REG(SYS_ATOP_TOT_CFG,				0x00066c),
-	REG(SYS_MAC_FC_CFG,				0x000670),
-	REG(SYS_MMGT,					0x00069c),
-	REG(SYS_MMGT_FAST,				0x0006a0),
-	REG(SYS_EVENTS_DIF,				0x0006a4),
-	REG(SYS_EVENTS_CORE,				0x0006b4),
-	REG(SYS_CNT,					0x000000),
-	REG(SYS_PTP_STATUS,				0x0006b8),
-	REG(SYS_PTP_TXSTAMP,				0x0006bc),
-	REG(SYS_PTP_NXT,				0x0006c0),
-	REG(SYS_PTP_CFG,				0x0006c4),
-};
-
-static const u32 ocelot_vcap_regmap[] = {
-	/* VCAP_CORE_CFG */
-	REG(VCAP_CORE_UPDATE_CTRL,			0x000000),
-	REG(VCAP_CORE_MV_CFG,				0x000004),
-	/* VCAP_CORE_CACHE */
-	REG(VCAP_CACHE_ENTRY_DAT,			0x000008),
-	REG(VCAP_CACHE_MASK_DAT,			0x000108),
-	REG(VCAP_CACHE_ACTION_DAT,			0x000208),
-	REG(VCAP_CACHE_CNT_DAT,				0x000308),
-	REG(VCAP_CACHE_TG_DAT,				0x000388),
-	/* VCAP_CONST */
-	REG(VCAP_CONST_VCAP_VER,			0x000398),
-	REG(VCAP_CONST_ENTRY_WIDTH,			0x00039c),
-	REG(VCAP_CONST_ENTRY_CNT,			0x0003a0),
-	REG(VCAP_CONST_ENTRY_SWCNT,			0x0003a4),
-	REG(VCAP_CONST_ENTRY_TG_WIDTH,			0x0003a8),
-	REG(VCAP_CONST_ACTION_DEF_CNT,			0x0003ac),
-	REG(VCAP_CONST_ACTION_WIDTH,			0x0003b0),
-	REG(VCAP_CONST_CNT_WIDTH,			0x0003b4),
-	REG(VCAP_CONST_CORE_CNT,			0x0003b8),
-	REG(VCAP_CONST_IF_CNT,				0x0003bc),
-};
-
-static const u32 ocelot_ptp_regmap[] = {
-	REG(PTP_PIN_CFG,				0x000000),
-	REG(PTP_PIN_TOD_SEC_MSB,			0x000004),
-	REG(PTP_PIN_TOD_SEC_LSB,			0x000008),
-	REG(PTP_PIN_TOD_NSEC,				0x00000c),
-	REG(PTP_PIN_WF_HIGH_PERIOD,			0x000014),
-	REG(PTP_PIN_WF_LOW_PERIOD,			0x000018),
-	REG(PTP_CFG_MISC,				0x0000a0),
-	REG(PTP_CLK_CFG_ADJ_CFG,			0x0000a4),
-	REG(PTP_CLK_CFG_ADJ_FREQ,			0x0000a8),
-};
-
-static const u32 ocelot_dev_gmii_regmap[] = {
-	REG(DEV_CLOCK_CFG,				0x0),
-	REG(DEV_PORT_MISC,				0x4),
-	REG(DEV_EVENTS,					0x8),
-	REG(DEV_EEE_CFG,				0xc),
-	REG(DEV_RX_PATH_DELAY,				0x10),
-	REG(DEV_TX_PATH_DELAY,				0x14),
-	REG(DEV_PTP_PREDICT_CFG,			0x18),
-	REG(DEV_MAC_ENA_CFG,				0x1c),
-	REG(DEV_MAC_MODE_CFG,				0x20),
-	REG(DEV_MAC_MAXLEN_CFG,				0x24),
-	REG(DEV_MAC_TAGS_CFG,				0x28),
-	REG(DEV_MAC_ADV_CHK_CFG,			0x2c),
-	REG(DEV_MAC_IFG_CFG,				0x30),
-	REG(DEV_MAC_HDX_CFG,				0x34),
-	REG(DEV_MAC_DBG_CFG,				0x38),
-	REG(DEV_MAC_FC_MAC_LOW_CFG,			0x3c),
-	REG(DEV_MAC_FC_MAC_HIGH_CFG,			0x40),
-	REG(DEV_MAC_STICKY,				0x44),
-	REG(PCS1G_CFG,					0x48),
-	REG(PCS1G_MODE_CFG,				0x4c),
-	REG(PCS1G_SD_CFG,				0x50),
-	REG(PCS1G_ANEG_CFG,				0x54),
-	REG(PCS1G_ANEG_NP_CFG,				0x58),
-	REG(PCS1G_LB_CFG,				0x5c),
-	REG(PCS1G_DBG_CFG,				0x60),
-	REG(PCS1G_CDET_CFG,				0x64),
-	REG(PCS1G_ANEG_STATUS,				0x68),
-	REG(PCS1G_ANEG_NP_STATUS,			0x6c),
-	REG(PCS1G_LINK_STATUS,				0x70),
-	REG(PCS1G_LINK_DOWN_CNT,			0x74),
-	REG(PCS1G_STICKY,				0x78),
-	REG(PCS1G_DEBUG_STATUS,				0x7c),
-	REG(PCS1G_LPI_CFG,				0x80),
-	REG(PCS1G_LPI_WAKE_ERROR_CNT,			0x84),
-	REG(PCS1G_LPI_STATUS,				0x88),
-	REG(PCS1G_TSTPAT_MODE_CFG,			0x8c),
-	REG(PCS1G_TSTPAT_STATUS,			0x90),
-	REG(DEV_PCS_FX100_CFG,				0x94),
-	REG(DEV_PCS_FX100_STATUS,			0x98),
-};
-
 static const u32 *ocelot_regmap[TARGET_MAX] = {
 	[ANA] = ocelot_ana_regmap,
 	[QS] = ocelot_qs_regmap,
diff --git a/include/soc/mscc/ocelot_regs.h b/include/soc/mscc/ocelot_regs.h
new file mode 100644
index 000000000000..d4508eb9e04a
--- /dev/null
+++ b/include/soc/mscc/ocelot_regs.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2021 Innovative Advantage Inc.
+ */
+
+#ifndef OCELOT_REGS_H
+#define OCELOT_REGS_H
+
+extern const u32 ocelot_ana_regmap[];
+extern const u32 ocelot_qs_regmap[];
+extern const u32 ocelot_qsys_regmap[];
+extern const u32 ocelot_rew_regmap[];
+extern const u32 ocelot_sys_regmap[];
+extern const u32 ocelot_vcap_regmap[];
+extern const u32 ocelot_ptp_regmap[];
+extern const u32 ocelot_dev_gmii_regmap[];
+
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (5 preceding siblings ...)
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file Colin Foster
@ 2021-08-14  2:50 ` Colin Foster
  2021-08-14 11:17   ` Vladimir Oltean
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 08/10] net: mscc: ocelot: felix: add ability to enable a CPU / NPI port Colin Foster
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:50 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Expose ocelot_wm functions so they can be shared with other drivers.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/ethernet/mscc/Makefile         |  1 +
 drivers/net/ethernet/mscc/ocelot_vsc7514.c | 28 ----------------
 drivers/net/ethernet/mscc/ocelot_wm.c      | 39 ++++++++++++++++++++++
 include/soc/mscc/ocelot.h                  |  5 +++
 4 files changed, 45 insertions(+), 28 deletions(-)
 create mode 100644 drivers/net/ethernet/mscc/ocelot_wm.c

diff --git a/drivers/net/ethernet/mscc/Makefile b/drivers/net/ethernet/mscc/Makefile
index d539a231a478..4ea9ecdfa60c 100644
--- a/drivers/net/ethernet/mscc/Makefile
+++ b/drivers/net/ethernet/mscc/Makefile
@@ -8,6 +8,7 @@ mscc_ocelot_switch_lib-y := \
 	ocelot_flower.o \
 	ocelot_ptp.o \
 	ocelot_regs.o \
+	ocelot_wm.o \
 	ocelot_devlink.o
 mscc_ocelot_switch_lib-$(CONFIG_BRIDGE_MRP) += ocelot_mrp.o
 obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot.o
diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
index ef1bf24f51b5..6e58f95a8dad 100644
--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
@@ -302,34 +302,6 @@ static int ocelot_reset(struct ocelot *ocelot)
 	return 0;
 }
 
-/* Watermark encode
- * Bit 8:   Unit; 0:1, 1:16
- * Bit 7-0: Value to be multiplied with unit
- */
-static u16 ocelot_wm_enc(u16 value)
-{
-	WARN_ON(value >= 16 * BIT(8));
-
-	if (value >= BIT(8))
-		return BIT(8) | (value / 16);
-
-	return value;
-}
-
-static u16 ocelot_wm_dec(u16 wm)
-{
-	if (wm & BIT(8))
-		return (wm & GENMASK(7, 0)) * 16;
-
-	return wm;
-}
-
-static void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse)
-{
-	*inuse = (val & GENMASK(23, 12)) >> 12;
-	*maxuse = val & GENMASK(11, 0);
-}
-
 static const struct ocelot_ops ocelot_ops = {
 	.reset			= ocelot_reset,
 	.wm_enc			= ocelot_wm_enc,
diff --git a/drivers/net/ethernet/mscc/ocelot_wm.c b/drivers/net/ethernet/mscc/ocelot_wm.c
new file mode 100644
index 000000000000..b21315b7b7f2
--- /dev/null
+++ b/drivers/net/ethernet/mscc/ocelot_wm.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#include "ocelot.h"
+
+/* Watermark encode
+ * Bit 8:   Unit; 0:1, 1:16
+ * Bit 7-0: Value to be multiplied with unit
+ */
+u16 ocelot_wm_enc(u16 value)
+{
+	WARN_ON(value >= 16 * BIT(8));
+
+	if (value >= BIT(8))
+		return BIT(8) | (value / 16);
+
+	return value;
+}
+EXPORT_SYMBOL(ocelot_wm_enc);
+
+u16 ocelot_wm_dec(u16 wm)
+{
+	if (wm & BIT(8))
+		return (wm & GENMASK(7, 0)) * 16;
+
+	return wm;
+}
+EXPORT_SYMBOL(ocelot_wm_dec);
+
+void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse)
+{
+	*inuse = (val & GENMASK(23, 12)) >> 12;
+	*maxuse = val & GENMASK(11, 0);
+}
+EXPORT_SYMBOL(ocelot_wm_stat);
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 2f5ce4d4fdbf..ff6e65a266d6 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -797,6 +797,11 @@ void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);
 void ocelot_deinit_port(struct ocelot *ocelot, int port);
 
+/* Watermark interface */
+u16 ocelot_wm_enc(u16 value);
+u16 ocelot_wm_dec(u16 wm);
+void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse);
+
 /* DSA callbacks */
 void ocelot_port_enable(struct ocelot *ocelot, int port,
 			struct phy_device *phy);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 08/10] net: mscc: ocelot: felix: add ability to enable a CPU / NPI port
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (6 preceding siblings ...)
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions Colin Foster
@ 2021-08-14  2:50 ` Colin Foster
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI Colin Foster
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device Colin Foster
  9 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:50 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

For the vsc7512 ocelot SPI driver, the CPU interface port needs to be enabled,
but can't be enabled via ocelot_adjust_link since it doesn't have a phylink.
This adds a hook so the port can be manually enabled.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/felix.c | 5 +++++
 drivers/net/dsa/ocelot/felix.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 77644deb4a35..33c0c7bc3e58 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -492,8 +492,13 @@ static void felix_teardown_tag_8021q(struct dsa_switch *ds, int cpu)
  */
 static void felix_npi_port_init(struct ocelot *ocelot, int port)
 {
+	struct felix *felix = ocelot_to_felix(ocelot);
+
 	ocelot->npi = port;
 
+	if (felix->info->enable_npi_port)
+		felix->info->enable_npi_port(ocelot);
+
 	ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
 		     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port),
 		     QSYS_EXT_CPU_CFG);
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 25f664ef4947..c872705115bc 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -47,6 +47,7 @@ struct felix_info {
 					u32 speed);
 	struct regmap *(*init_regmap)(struct ocelot *ocelot,
 				      struct resource *res);
+	void	(*enable_npi_port)(struct ocelot *ocelot);
 };
 
 extern const struct dsa_switch_ops felix_switch_ops;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (7 preceding siblings ...)
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 08/10] net: mscc: ocelot: felix: add ability to enable a CPU / NPI port Colin Foster
@ 2021-08-14  2:50 ` Colin Foster
  2021-08-14 11:43   ` Vladimir Oltean
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device Colin Foster
  9 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:50 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Utilize the Felix and Ocelot drivers to allow control of the VSC7511,
VSC7512, VSC7513 and VSC7514 chips from an external CPU over SPI.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/Kconfig              |   13 +
 drivers/net/dsa/ocelot/Makefile             |    6 +
 drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c | 1133 +++++++++++++++++++
 drivers/net/ethernet/mscc/ocelot.c          |    8 +
 include/soc/mscc/ocelot.h                   |   19 +
 5 files changed, 1179 insertions(+)
 create mode 100644 drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c

diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index 61bcc88ae4c1..bd7354b4187f 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig
@@ -14,6 +14,19 @@ config NET_DSA_MSCC_FELIX
 	  This driver supports the VSC9959 (Felix) switch, which is embedded as
 	  a PCIe function of the NXP LS1028A ENETC RCiEP.
 
+config NET_DSA_MSCC_OCELOT_SPI
+	tristate "Ocelot Ethernet SPI switch support"
+	depends on NET_DSA && SPI
+	depends on NET_VENDOR_MICROSEMI
+	select MDIO_MSCC_MIIM
+	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. It can be used with the Microsemi dev
+	  boards and an external CPU or custom hardware.
+
 config NET_DSA_MSCC_SEVILLE
 	tristate "Ocelot / Seville Ethernet switch support"
 	depends on NET_DSA
diff --git a/drivers/net/dsa/ocelot/Makefile b/drivers/net/dsa/ocelot/Makefile
index 34b9b128efb8..6ccd5482de7b 100644
--- a/drivers/net/dsa/ocelot/Makefile
+++ b/drivers/net/dsa/ocelot/Makefile
@@ -1,11 +1,17 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
+obj-$(CONFIG_NET_DSA_MSCC_OCELOT_SPI) += mscc_ocelot_spi.o
 obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o
 
 mscc_felix-objs := \
 	felix.o \
 	felix_vsc9959.o
 
+mscc_ocelot_spi-objs := \
+	felix.o \
+	felix_mdio.o \
+	ocelot_vsc7512_spi.o
+
 mscc_seville-objs := \
 	felix.o \
 	felix_mdio.o \
diff --git a/drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c b/drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c
new file mode 100644
index 000000000000..51c9f17960ec
--- /dev/null
+++ b/drivers/net/dsa/ocelot/ocelot_vsc7512_spi.c
@@ -0,0 +1,1133 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright 2017 Microsemi Corporation
+ * Copyright 2018-2019 NXP Semiconductors
+ * Copyright 2021 Innovative Advantage Inc.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/spi/spi.h>
+#include <linux/iopoll.h>
+#include <linux/kconfig.h>
+#include <linux/mdio.h>
+#include <linux/regmap.h>
+#include <soc/mscc/ocelot_ana.h>
+#include <soc/mscc/ocelot_dev.h>
+#include <soc/mscc/ocelot_qsys.h>
+#include <soc/mscc/ocelot_vcap.h>
+#include <soc/mscc/ocelot_ptp.h>
+#include <soc/mscc/ocelot_regs.h>
+#include <soc/mscc/ocelot_sys.h>
+#include <soc/mscc/ocelot.h>
+#include "felix.h"
+#include "felix_mdio.h"
+
+struct ocelot_spi_data {
+	int spi_padding_bytes;
+	struct felix felix;
+	struct spi_device *spi;
+};
+
+static const u32 vsc7512_dev_cpuorg_regmap[] = {
+	REG(DEV_CPUORG_IF_CTRL,			0x0000),
+	REG(DEV_CPUORG_IF_CFGSTAT,		0x0004),
+	REG(DEV_CPUORG_ORG_CFG,			0x0008),
+	REG(DEV_CPUORG_ERR_CNTS,		0x000c),
+	REG(DEV_CPUORG_TIMEOUT_CFG,		0x0010),
+	REG(DEV_CPUORG_GPR,			0x0014),
+	REG(DEV_CPUORG_MAILBOX_SET,		0x0018),
+	REG(DEV_CPUORG_MAILBOX_CLR,		0x001c),
+	REG(DEV_CPUORG_MAILBOX,			0x0020),
+	REG(DEV_CPUORG_SEMA_CFG,		0x0024),
+	REG(DEV_CPUORG_SEMA0,			0x0028),
+	REG(DEV_CPUORG_SEMA0_OWNER,		0x002c),
+	REG(DEV_CPUORG_SEMA1,			0x0030),
+	REG(DEV_CPUORG_SEMA1_OWNER,		0x0034),
+};
+
+static const u32 vsc7512_gcb_regmap[] = {
+	REG(GCB_SOFT_RST,			0x0008),
+	REG(GCB_MIIM_MII_STATUS,		0x009c),
+	REG(GCB_MIIM_MII_CMD,			0x00a4),
+	REG(GCB_MIIM_MII_DATA,			0x00a8),
+	REG(GCB_PHY_PHY_CFG,			0x00f0),
+	REG(GCB_PHY_PHY_STAT,			0x00f4),
+};
+
+static const u32 *vsc7512_regmap[TARGET_MAX] = {
+	[ANA] = ocelot_ana_regmap,
+	[QS] = ocelot_qs_regmap,
+	[QSYS] = ocelot_qsys_regmap,
+	[REW] = ocelot_rew_regmap,
+	[SYS] = ocelot_sys_regmap,
+	[S0] = ocelot_vcap_regmap,
+	[S1] = ocelot_vcap_regmap,
+	[S2] = ocelot_vcap_regmap,
+	[PTP] = ocelot_ptp_regmap,
+	[GCB] = vsc7512_gcb_regmap,
+	[DEV_GMII] = ocelot_dev_gmii_regmap,
+	[DEV_CPUORG] = vsc7512_dev_cpuorg_regmap,
+};
+
+#define VSC7512_BYTE_ORDER_LE 0x00000000
+#define VSC7512_BYTE_ORDER_BE 0x81818181
+#define VSC7512_BIT_ORDER_MSB 0x00000000
+#define VSC7512_BIT_ORDER_LSB 0x42424242
+
+static void ocelot_spi_reset_phys(struct ocelot *ocelot)
+{
+	ocelot_write(ocelot, 0, GCB_PHY_PHY_CFG);
+	ocelot_write(ocelot, 0x1ff, GCB_PHY_PHY_CFG);
+	mdelay(500);
+}
+
+static struct ocelot_spi_data *felix_to_ocelot_spi(struct felix *felix)
+{
+	return container_of(felix, struct ocelot_spi_data, felix);
+}
+
+static struct ocelot_spi_data *ocelot_to_ocelot_spi(struct ocelot *ocelot)
+{
+	struct felix *felix = ocelot_to_felix(ocelot);
+
+	return felix_to_ocelot_spi(felix);
+}
+
+static int ocelot_spi_init_bus(struct ocelot *ocelot)
+{
+	struct ocelot_spi_data *ocelot_spi;
+	struct spi_device *spi;
+	u32 val, check;
+
+	ocelot_spi = ocelot_to_ocelot_spi(ocelot);
+	spi = ocelot_spi->spi;
+
+	val = 0;
+
+#ifdef __LITTLE_ENDIAN
+	val |= VSC7512_BYTE_ORDER_LE;
+#else
+	val |= VSC7512_BYTE_ORDER_BE;
+#endif
+
+	ocelot_write(ocelot, val, DEV_CPUORG_IF_CTRL);
+
+	val = ocelot_spi->spi_padding_bytes;
+	ocelot_write(ocelot, val, DEV_CPUORG_IF_CFGSTAT);
+
+	check = val | 0x02000000;
+
+	val = ocelot_read(ocelot, DEV_CPUORG_IF_CFGSTAT);
+	if (check != val) {
+		dev_err(&spi->dev,
+			"Error configuring SPI bus. V: 0x%08x != 0x%08x\n", val,
+			check);
+		return -ENODEV;
+	}
+
+	/* The internal copper phys need to be enabled before the mdio bus is
+	 * scanned.
+	 */
+	ocelot_spi_reset_phys(ocelot);
+
+	return 0;
+}
+
+static int vsc7512_reset(struct ocelot *ocelot)
+{
+	int retries = 100;
+	int ret, val;
+
+	ocelot_field_write(ocelot, GCB_SOFT_RST_CHIP_RST, 1);
+
+	/* Note: This is adapted from the PCIe reset strategy. The manual doesn't
+	 * suggest how to do a reset over SPI, and the register strategy isn't
+	 * possible.
+	 */
+	msleep(100);
+
+	ret = ocelot_spi_init_bus(ocelot);
+	if (ret)
+		return ret;
+
+	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
+	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
+
+	do {
+		msleep(1);
+		regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
+				  &val);
+	} while (val && --retries);
+
+	if (!retries)
+		return -ETIMEDOUT;
+
+	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
+
+	return 0;
+}
+
+static int vsc7512_spi_bus_init(struct ocelot *ocelot)
+{
+	struct felix *felix = ocelot_to_felix(ocelot);
+	int rval;
+
+	rval = ocelot_spi_init_bus(ocelot);
+	if (rval) {
+		dev_err(ocelot->dev, "error initializing SPI bus\n");
+		goto clear_mdio;
+	}
+
+	rval = felix_mdio_register(ocelot);
+	if (rval)
+		dev_err(ocelot->dev, "error registering MDIO bus\n");
+
+	felix->ds->slave_mii_bus = felix->imdio;
+
+	return rval;
+
+clear_mdio:
+	felix->imdio = NULL;
+	return rval;
+}
+
+static const struct ocelot_ops vsc7512_ops = {
+	.bus_init	= vsc7512_spi_bus_init,
+	.reset		= vsc7512_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,
+};
+
+/* Addresses are relative to the SPI device's base address, downshifted by 2*/
+static const struct resource vsc7512_target_io_res[TARGET_MAX] = {
+	[ANA] = {
+		.start	= 0x71880000,
+		.end	= 0x7188ffff,
+		.name	= "ana",
+	},
+	[QS] = {
+		.start	= 0x71080000,
+		.end	= 0x710800ff,
+		.name	= "qs",
+	},
+	[QSYS] = {
+		.start	= 0x71800000,
+		.end	= 0x719fffff,
+		.name	= "qsys",
+	},
+	[REW] = {
+		.start	= 0x71030000,
+		.end	= 0x7103ffff,
+		.name	= "rew",
+	},
+	[SYS] = {
+		.start	= 0x71010000,
+		.end	= 0x7101ffff,
+		.name	= "sys",
+	},
+	[S0] = {
+		.start	= 0x71040000,
+		.end	= 0x710403ff,
+		.name	= "s0",
+	},
+	[S1] = {
+		.start	= 0x71050000,
+		.end	= 0x710503ff,
+		.name	= "s1",
+	},
+	[S2] = {
+		.start	= 0x71060000,
+		.end	= 0x710603ff,
+		.name	= "s2",
+	},
+	[GCB] =	{
+		.start	= 0x71070000,
+		.end	= 0x710701ff,
+		.name	= "devcpu_gcb",
+	},
+	[DEV_CPUORG] = {
+		.start	= 0x71000000,
+		.end	= 0x710003ff,
+		.name	= "devcpu_org",
+	},
+};
+
+static const struct resource vsc7512_port_io_res[] = {
+	{
+		.start	= 0x711e0000,
+		.end	= 0x711effff,
+		.name	= "port0",
+	},
+	{
+		.start	= 0x711f0000,
+		.end	= 0x711fffff,
+		.name	= "port1",
+	},
+	{
+		.start	= 0x71200000,
+		.end	= 0x7120ffff,
+		.name	= "port2",
+	},
+	{
+		.start	= 0x71210000,
+		.end	= 0x7121ffff,
+		.name	= "port3",
+	},
+	{
+		.start	= 0x71220000,
+		.end	= 0x7122ffff,
+		.name	= "port4",
+	},
+	{
+		.start	= 0x71230000,
+		.end	= 0x7123ffff,
+		.name	= "port5",
+	},
+	{
+		.start	= 0x71240000,
+		.end	= 0x7124ffff,
+		.name	= "port6",
+	},
+	{
+		.start	= 0x71250000,
+		.end	= 0x7125ffff,
+		.name	= "port7",
+	},
+	{
+		.start	= 0x71260000,
+		.end	= 0x7126ffff,
+		.name	= "port8",
+	},
+	{
+		.start	= 0x71270000,
+		.end	= 0x7127ffff,
+		.name	= "port9",
+	},
+	{
+		.start	= 0x71280000,
+		.end	= 0x7128ffff,
+		.name	= "port10",
+	},
+};
+
+static const struct reg_field vsc7512_regfields[REGFIELD_MAX] = {
+	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11),
+	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10),
+	[ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27),
+	[ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26),
+	[ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25),
+	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24),
+	[ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23),
+	[ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22),
+	[ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21),
+	[ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20),
+	[ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19),
+	[ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18),
+	[ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17),
+	[ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16),
+	[ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15),
+	[ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14),
+	[ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13),
+	[ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12),
+	[ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11),
+	[ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10),
+	[ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9),
+	[ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8),
+	[ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7),
+	[ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),
+	[ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),
+	[ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4),
+	[ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3),
+	[ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2),
+	[ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1),
+	[ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0),
+	[ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18),
+	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11),
+	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9),
+	[GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 1, 1),
+	[GCB_SOFT_RST_CHIP_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0),
+	[QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20),
+	[QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19),
+	[QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7),
+	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3),
+	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0),
+	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2),
+	[SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1),
+	[SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0),
+	/* Replicated per number of ports (12), register size 4 per port */
+	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4),
+	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4),
+	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4),
+	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4),
+	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4),
+	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4),
+	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4),
+	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4),
+	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4),
+	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4),
+	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4),
+	[GCB_MIIM_MII_STATUS_PENDING] = REG_FIELD(GCB_MIIM_MII_STATUS, 2, 2),
+	[GCB_MIIM_MII_STATUS_BUSY] = REG_FIELD(GCB_MIIM_MII_STATUS, 3, 3),
+};
+
+static const struct ocelot_stat_layout vsc7512_stats_layout[] = {
+	{ .offset = 0x00,	.name = "rx_octets", },
+	{ .offset = 0x01,	.name = "rx_unicast", },
+	{ .offset = 0x02,	.name = "rx_multicast", },
+	{ .offset = 0x03,	.name = "rx_broadcast", },
+	{ .offset = 0x04,	.name = "rx_shorts", },
+	{ .offset = 0x05,	.name = "rx_fragments", },
+	{ .offset = 0x06,	.name = "rx_jabbers", },
+	{ .offset = 0x07,	.name = "rx_crc_align_errs", },
+	{ .offset = 0x08,	.name = "rx_sym_errs", },
+	{ .offset = 0x09,	.name = "rx_frames_below_65_octets", },
+	{ .offset = 0x0A,	.name = "rx_frames_65_to_127_octets", },
+	{ .offset = 0x0B,	.name = "rx_frames_128_to_255_octets", },
+	{ .offset = 0x0C,	.name = "rx_frames_256_to_511_octets", },
+	{ .offset = 0x0D,	.name = "rx_frames_512_to_1023_octets", },
+	{ .offset = 0x0E,	.name = "rx_frames_1024_to_1526_octets", },
+	{ .offset = 0x0F,	.name = "rx_frames_over_1526_octets", },
+	{ .offset = 0x10,	.name = "rx_pause", },
+	{ .offset = 0x11,	.name = "rx_control", },
+	{ .offset = 0x12,	.name = "rx_longs", },
+	{ .offset = 0x13,	.name = "rx_classified_drops", },
+	{ .offset = 0x14,	.name = "rx_red_prio_0", },
+	{ .offset = 0x15,	.name = "rx_red_prio_1", },
+	{ .offset = 0x16,	.name = "rx_red_prio_2", },
+	{ .offset = 0x17,	.name = "rx_red_prio_3", },
+	{ .offset = 0x18,	.name = "rx_red_prio_4", },
+	{ .offset = 0x19,	.name = "rx_red_prio_5", },
+	{ .offset = 0x1A,	.name = "rx_red_prio_6", },
+	{ .offset = 0x1B,	.name = "rx_red_prio_7", },
+	{ .offset = 0x1C,	.name = "rx_yellow_prio_0", },
+	{ .offset = 0x1D,	.name = "rx_yellow_prio_1", },
+	{ .offset = 0x1E,	.name = "rx_yellow_prio_2", },
+	{ .offset = 0x1F,	.name = "rx_yellow_prio_3", },
+	{ .offset = 0x20,	.name = "rx_yellow_prio_4", },
+	{ .offset = 0x21,	.name = "rx_yellow_prio_5", },
+	{ .offset = 0x22,	.name = "rx_yellow_prio_6", },
+	{ .offset = 0x23,	.name = "rx_yellow_prio_7", },
+	{ .offset = 0x24,	.name = "rx_green_prio_0", },
+	{ .offset = 0x25,	.name = "rx_green_prio_1", },
+	{ .offset = 0x26,	.name = "rx_green_prio_2", },
+	{ .offset = 0x27,	.name = "rx_green_prio_3", },
+	{ .offset = 0x28,	.name = "rx_green_prio_4", },
+	{ .offset = 0x29,	.name = "rx_green_prio_5", },
+	{ .offset = 0x2A,	.name = "rx_green_prio_6", },
+	{ .offset = 0x2B,	.name = "rx_green_prio_7", },
+	{ .offset = 0x40,	.name = "tx_octets", },
+	{ .offset = 0x41,	.name = "tx_unicast", },
+	{ .offset = 0x42,	.name = "tx_multicast", },
+	{ .offset = 0x43,	.name = "tx_broadcast", },
+	{ .offset = 0x44,	.name = "tx_collision", },
+	{ .offset = 0x45,	.name = "tx_drops", },
+	{ .offset = 0x46,	.name = "tx_pause", },
+	{ .offset = 0x47,	.name = "tx_frames_below_65_octets", },
+	{ .offset = 0x48,	.name = "tx_frames_65_to_127_octets", },
+	{ .offset = 0x49,	.name = "tx_frames_128_255_octets", },
+	{ .offset = 0x4A,	.name = "tx_frames_256_511_octets", },
+	{ .offset = 0x4B,	.name = "tx_frames_512_1023_octets", },
+	{ .offset = 0x4C,	.name = "tx_frames_1024_1526_octets", },
+	{ .offset = 0x4D,	.name = "tx_frames_over_1526_octets", },
+	{ .offset = 0x4E,	.name = "tx_yellow_prio_0", },
+	{ .offset = 0x4F,	.name = "tx_yellow_prio_1", },
+	{ .offset = 0x50,	.name = "tx_yellow_prio_2", },
+	{ .offset = 0x51,	.name = "tx_yellow_prio_3", },
+	{ .offset = 0x52,	.name = "tx_yellow_prio_4", },
+	{ .offset = 0x53,	.name = "tx_yellow_prio_5", },
+	{ .offset = 0x54,	.name = "tx_yellow_prio_6", },
+	{ .offset = 0x55,	.name = "tx_yellow_prio_7", },
+	{ .offset = 0x56,	.name = "tx_green_prio_0", },
+	{ .offset = 0x57,	.name = "tx_green_prio_1", },
+	{ .offset = 0x58,	.name = "tx_green_prio_2", },
+	{ .offset = 0x59,	.name = "tx_green_prio_3", },
+	{ .offset = 0x5A,	.name = "tx_green_prio_4", },
+	{ .offset = 0x5B,	.name = "tx_green_prio_5", },
+	{ .offset = 0x5C,	.name = "tx_green_prio_6", },
+	{ .offset = 0x5D,	.name = "tx_green_prio_7", },
+	{ .offset = 0x5E,	.name = "tx_aged", },
+	{ .offset = 0x80,	.name = "drop_local", },
+	{ .offset = 0x81,	.name = "drop_tail", },
+	{ .offset = 0x82,	.name = "drop_yellow_prio_0", },
+	{ .offset = 0x83,	.name = "drop_yellow_prio_1", },
+	{ .offset = 0x84,	.name = "drop_yellow_prio_2", },
+	{ .offset = 0x85,	.name = "drop_yellow_prio_3", },
+	{ .offset = 0x86,	.name = "drop_yellow_prio_4", },
+	{ .offset = 0x87,	.name = "drop_yellow_prio_5", },
+	{ .offset = 0x88,	.name = "drop_yellow_prio_6", },
+	{ .offset = 0x89,	.name = "drop_yellow_prio_7", },
+	{ .offset = 0x8A,	.name = "drop_green_prio_0", },
+	{ .offset = 0x8B,	.name = "drop_green_prio_1", },
+	{ .offset = 0x8C,	.name = "drop_green_prio_2", },
+	{ .offset = 0x8D,	.name = "drop_green_prio_3", },
+	{ .offset = 0x8E,	.name = "drop_green_prio_4", },
+	{ .offset = 0x8F,	.name = "drop_green_prio_5", },
+	{ .offset = 0x90,	.name = "drop_green_prio_6", },
+	{ .offset = 0x91,	.name = "drop_green_prio_7", },
+};
+
+static unsigned int ocelot_spi_translate_address(unsigned int reg)
+{
+	return cpu_to_be32((reg & 0xffffff) >> 2);
+}
+
+struct ocelot_spi_regmap_context {
+	struct spi_device *spi;
+	u32 base;
+};
+
+static int ocelot_spi_reg_read(void *context, unsigned int reg,
+			       unsigned int *val)
+{
+	struct ocelot_spi_regmap_context *regmap_context = context;
+	struct spi_transfer tx, padding, rx;
+	struct ocelot_spi_data *ocelot_spi;
+	struct spi_message msg;
+	struct spi_device *spi;
+	unsigned int addr;
+	u8 *tx_buf;
+
+	WARN_ON(!val);
+
+	spi = regmap_context->spi;
+
+	ocelot_spi = spi_get_drvdata(spi);
+
+	addr = ocelot_spi_translate_address(reg + regmap_context->base);
+	tx_buf = (u8 *)&addr;
+
+	spi_message_init(&msg);
+
+	memset(&tx, 0, sizeof(struct spi_transfer));
+
+	/* Ignore the first byte for the 24-bit address */
+	tx.tx_buf = &tx_buf[1];
+	tx.len = 3;
+
+	spi_message_add_tail(&tx, &msg);
+
+	if (ocelot_spi->spi_padding_bytes > 0) {
+		u8 dummy_buf[16] = {0};
+
+		memset(&padding, 0, sizeof(struct spi_transfer));
+
+		/* Just toggle the clock for padding bytes */
+		padding.len = ocelot_spi->spi_padding_bytes;
+		padding.tx_buf = dummy_buf;
+		padding.dummy_data = 1;
+
+		spi_message_add_tail(&padding, &msg);
+	}
+
+	memset(&rx, 0, sizeof(struct spi_transfer));
+	rx.rx_buf = val;
+	rx.len = 4;
+
+	spi_message_add_tail(&rx, &msg);
+
+	return spi_sync(spi, &msg);
+}
+
+static int ocelot_spi_reg_write(void *context, unsigned int reg,
+				unsigned int val)
+{
+	struct ocelot_spi_regmap_context *regmap_context = context;
+	struct spi_transfer tx[2] = {0};
+	struct spi_message msg;
+	struct spi_device *spi;
+	unsigned int addr;
+	u8 *tx_buf;
+
+	spi = regmap_context->spi;
+
+	addr = ocelot_spi_translate_address(reg + regmap_context->base);
+	tx_buf = (u8 *)&addr;
+
+	spi_message_init(&msg);
+
+	/* Ignore the first byte for the 24-bit address and set the write bit */
+	tx_buf[1] |= BIT(7);
+	tx[0].tx_buf = &tx_buf[1];
+	tx[0].len = 3;
+
+	spi_message_add_tail(&tx[0], &msg);
+
+	memset(&tx[1], 0, sizeof(struct spi_transfer));
+	tx[1].tx_buf = &val;
+	tx[1].len = 4;
+
+	spi_message_add_tail(&tx[1], &msg);
+
+	return spi_sync(spi, &msg);
+}
+
+static const struct regmap_config ocelot_spi_regmap_config = {
+	.reg_bits = 24,
+	.reg_stride = 4,
+	.val_bits = 32,
+
+	.reg_read = ocelot_spi_reg_read,
+	.reg_write = ocelot_spi_reg_write,
+
+	.max_register = 0xffffffff,
+	.use_single_write = true,
+	.use_single_read = true,
+	.can_multi_write = false,
+
+	.reg_format_endian = REGMAP_ENDIAN_BIG,
+	.val_format_endian = REGMAP_ENDIAN_NATIVE,
+};
+
+static void vsc7512_phylink_validate(struct ocelot *ocelot, int port,
+				     unsigned long *supported,
+				     struct phylink_link_state *state)
+{
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+
+	if (state->interface != PHY_INTERFACE_MODE_NA &&
+	    state->interface != ocelot_port->phy_mode) {
+		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+		return;
+	}
+
+	phylink_set_port_modes(mask);
+
+	phylink_set(mask, Pause);
+	phylink_set(mask, Autoneg);
+	phylink_set(mask, Asym_Pause);
+	phylink_set(mask, 10baseT_Half);
+	phylink_set(mask, 10baseT_Full);
+	phylink_set(mask, 100baseT_Half);
+	phylink_set(mask, 100baseT_Full);
+	phylink_set(mask, 1000baseT_Half);
+	phylink_set(mask, 1000baseT_Full);
+
+	bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
+	bitmap_and(state->advertising, state->advertising, mask,
+		   __ETHTOOL_LINK_MODE_MASK_NBITS);
+}
+
+static int vsc7512_prevalidate_phy_mode(struct ocelot *ocelot, int port,
+					phy_interface_t phy_mode)
+{
+	switch (phy_mode) {
+	case PHY_INTERFACE_MODE_INTERNAL:
+		if (port < 4)
+			return 0;
+		return -EOPNOTSUPP;
+	case PHY_INTERFACE_MODE_SGMII:
+		if (port < 8)
+			return 0;
+		return -EOPNOTSUPP;
+	case PHY_INTERFACE_MODE_QSGMII:
+		if (port == 7 || port == 8 || port == 10)
+			return 0;
+		return -EOPNOTSUPP;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int vsc7512_port_setup_tc(struct dsa_switch *ds, int port,
+				 enum tc_setup_type type, void *type_data)
+{
+	return -EOPNOTSUPP;
+}
+
+static const struct vcap_field vsc7512_vcap_es0_keys[] = {
+	[VCAP_ES0_EGR_PORT]			= { 0,   4 },
+	[VCAP_ES0_IGR_PORT]			= { 4,   4 },
+	[VCAP_ES0_RSV]				= { 8,   2 },
+	[VCAP_ES0_L2_MC]			= { 10,  1 },
+	[VCAP_ES0_L2_BC]			= { 11,  1 },
+	[VCAP_ES0_VID]				= { 12, 12 },
+	[VCAP_ES0_DP]				= { 24,  1 },
+	[VCAP_ES0_PCP]				= { 25,  3 },
+};
+
+static const struct vcap_field vsc7512_vcap_es0_actions[]   = {
+	[VCAP_ES0_ACT_PUSH_OUTER_TAG]		= { 0,   2 },
+	[VCAP_ES0_ACT_PUSH_INNER_TAG]		= { 2,   1 },
+	[VCAP_ES0_ACT_TAG_A_TPID_SEL]		= { 3,   2 },
+	[VCAP_ES0_ACT_TAG_A_VID_SEL]		= { 5,   1 },
+	[VCAP_ES0_ACT_TAG_A_PCP_SEL]		= { 6,   2 },
+	[VCAP_ES0_ACT_TAG_A_DEI_SEL]		= { 8,   2 },
+	[VCAP_ES0_ACT_TAG_B_TPID_SEL]		= { 10,  2 },
+	[VCAP_ES0_ACT_TAG_B_VID_SEL]		= { 12,  1 },
+	[VCAP_ES0_ACT_TAG_B_PCP_SEL]		= { 13,  2 },
+	[VCAP_ES0_ACT_TAG_B_DEI_SEL]		= { 15,  2 },
+	[VCAP_ES0_ACT_VID_A_VAL]		= { 17, 12 },
+	[VCAP_ES0_ACT_PCP_A_VAL]		= { 29,  3 },
+	[VCAP_ES0_ACT_DEI_A_VAL]		= { 32,  1 },
+	[VCAP_ES0_ACT_VID_B_VAL]		= { 33, 12 },
+	[VCAP_ES0_ACT_PCP_B_VAL]		= { 45,  3 },
+	[VCAP_ES0_ACT_DEI_B_VAL]		= { 48,  1 },
+	[VCAP_ES0_ACT_RSV]			= { 49, 24 },
+	[VCAP_ES0_ACT_HIT_STICKY]		= { 73,  1 },
+};
+
+static const struct vcap_field vsc7512_vcap_is1_keys[] = {
+	[VCAP_IS1_HK_TYPE]			= { 0,    1 },
+	[VCAP_IS1_HK_LOOKUP]			= { 1,    2 },
+	[VCAP_IS1_HK_IGR_PORT_MASK]		= { 3,   12 },
+	[VCAP_IS1_HK_RSV]			= { 15,   9 },
+	[VCAP_IS1_HK_OAM_Y1731]			= { 24,   1 },
+	[VCAP_IS1_HK_L2_MC]			= { 25,   1 },
+	[VCAP_IS1_HK_L2_BC]			= { 26,   1 },
+	[VCAP_IS1_HK_IP_MC]			= { 27,   1 },
+	[VCAP_IS1_HK_VLAN_TAGGED]		= { 28,   1 },
+	[VCAP_IS1_HK_VLAN_DBL_TAGGED]		= { 29,   1 },
+	[VCAP_IS1_HK_TPID]			= { 30,   1 },
+	[VCAP_IS1_HK_VID]			= { 31,  12 },
+	[VCAP_IS1_HK_DEI]			= { 43,   1 },
+	[VCAP_IS1_HK_PCP]			= { 44,   3 },
+	/* Specific Fields for IS1 Half Key S1_NORMAL */
+	[VCAP_IS1_HK_L2_SMAC]			= { 47,  48 },
+	[VCAP_IS1_HK_ETYPE_LEN]			= { 95,   1 },
+	[VCAP_IS1_HK_ETYPE]			= { 96,  16 },
+	[VCAP_IS1_HK_IP_SNAP]			= { 112,  1 },
+	[VCAP_IS1_HK_IP4]			= { 113,  1 },
+	/* Layer-3 Information */
+	[VCAP_IS1_HK_L3_FRAGMENT]		= { 114,  1 },
+	[VCAP_IS1_HK_L3_FRAG_OFS_GT0]		= { 115,  1 },
+	[VCAP_IS1_HK_L3_OPTIONS]		= { 116,  1 },
+	[VCAP_IS1_HK_L3_DSCP]			= { 117,  6 },
+	[VCAP_IS1_HK_L3_IP4_SIP]		= { 123, 32 },
+	/* Layer-4 Information */
+	[VCAP_IS1_HK_TCP_UDP]			= { 155,  1 },
+	[VCAP_IS1_HK_TCP]			= { 156,  1 },
+	[VCAP_IS1_HK_L4_SPORT]			= { 157, 16 },
+	[VCAP_IS1_HK_L4_RNG]			= { 173,  8 },
+	/* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */
+	[VCAP_IS1_HK_IP4_INNER_TPID]		= { 47,   1 },
+	[VCAP_IS1_HK_IP4_INNER_VID]		= { 48,  12 },
+	[VCAP_IS1_HK_IP4_INNER_DEI]		= { 60,   1 },
+	[VCAP_IS1_HK_IP4_INNER_PCP]		= { 61,   3 },
+	[VCAP_IS1_HK_IP4_IP4]			= { 64,   1 },
+	[VCAP_IS1_HK_IP4_L3_FRAGMENT]		= { 65,   1 },
+	[VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0]	= { 66,   1 },
+	[VCAP_IS1_HK_IP4_L3_OPTIONS]		= { 67,   1 },
+	[VCAP_IS1_HK_IP4_L3_DSCP]		= { 68,   6 },
+	[VCAP_IS1_HK_IP4_L3_IP4_DIP]		= { 74,  32 },
+	[VCAP_IS1_HK_IP4_L3_IP4_SIP]		= { 106, 32 },
+	[VCAP_IS1_HK_IP4_L3_PROTO]		= { 138,  8 },
+	[VCAP_IS1_HK_IP4_TCP_UDP]		= { 146,  1 },
+	[VCAP_IS1_HK_IP4_TCP]			= { 147,  1 },
+	[VCAP_IS1_HK_IP4_L4_RNG]		= { 148,  8 },
+	[VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE]	= { 156, 32 },
+};
+
+static const struct vcap_field vsc7512_vcap_is1_actions[] = {
+	[VCAP_IS1_ACT_DSCP_ENA]			= { 0,   1 },
+	[VCAP_IS1_ACT_DSCP_VAL]			= { 1,   6 },
+	[VCAP_IS1_ACT_QOS_ENA]			= { 7,   1 },
+	[VCAP_IS1_ACT_QOS_VAL]			= { 8,   3 },
+	[VCAP_IS1_ACT_DP_ENA]			= { 11,  1 },
+	[VCAP_IS1_ACT_DP_VAL]			= { 12,  1 },
+	[VCAP_IS1_ACT_PAG_OVERRIDE_MASK]	= { 13,  8 },
+	[VCAP_IS1_ACT_PAG_VAL]			= { 21,  8 },
+	[VCAP_IS1_ACT_RSV]			= { 29,  9 },
+	/* The fields below are incorrectly shifted by 2 in the manual */
+	[VCAP_IS1_ACT_VID_REPLACE_ENA]		= { 38,  1 },
+	[VCAP_IS1_ACT_VID_ADD_VAL]		= { 39, 12 },
+	[VCAP_IS1_ACT_FID_SEL]			= { 51,  2 },
+	[VCAP_IS1_ACT_FID_VAL]			= { 53, 13 },
+	[VCAP_IS1_ACT_PCP_DEI_ENA]		= { 66,  1 },
+	[VCAP_IS1_ACT_PCP_VAL]			= { 67,  3 },
+	[VCAP_IS1_ACT_DEI_VAL]			= { 70,  1 },
+	[VCAP_IS1_ACT_VLAN_POP_CNT_ENA]		= { 71,  1 },
+	[VCAP_IS1_ACT_VLAN_POP_CNT]		= { 72,  2 },
+	[VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA]	= { 74,  4 },
+	[VCAP_IS1_ACT_HIT_STICKY]		= { 78,  1 },
+};
+
+static const struct vcap_field vsc7512_vcap_is2_keys[] = {
+	/* Common: 46 bits */
+	[VCAP_IS2_TYPE]				= { 0,    4 },
+	[VCAP_IS2_HK_FIRST]			= { 4,    1 },
+	[VCAP_IS2_HK_PAG]			= { 5,    8 },
+	[VCAP_IS2_HK_IGR_PORT_MASK]		= { 13,  12 },
+	[VCAP_IS2_HK_RSV2]			= { 25,   1 },
+	[VCAP_IS2_HK_HOST_MATCH]		= { 26,   1 },
+	[VCAP_IS2_HK_L2_MC]			= { 27,   1 },
+	[VCAP_IS2_HK_L2_BC]			= { 28,   1 },
+	[VCAP_IS2_HK_VLAN_TAGGED]		= { 29,   1 },
+	[VCAP_IS2_HK_VID]			= { 30,  12 },
+	[VCAP_IS2_HK_DEI]			= { 42,   1 },
+	[VCAP_IS2_HK_PCP]			= { 43,   3 },
+	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
+	[VCAP_IS2_HK_L2_DMAC]			= { 46,  48 },
+	[VCAP_IS2_HK_L2_SMAC]			= { 94,  48 },
+	/* MAC_ETYPE (TYPE=000) */
+	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= { 142, 16 },
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= { 158, 16 },
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= { 174,  8 },
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= { 182,  3 },
+	/* MAC_LLC (TYPE=001) */
+	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= { 142, 40 },
+	/* MAC_SNAP (TYPE=010) */
+	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= { 142, 40 },
+	/* MAC_ARP (TYPE=011) */
+	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 46,  48 },
+	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 94,   1 },
+	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 95,   1 },
+	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 96,   1 },
+	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 97,   1 },
+	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 98,   1 },
+	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 99,   1 },
+	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= { 100,  2 },
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= { 102, 32 },
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= { 134, 32 },
+	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= { 166,  1 },
+	/* IP4_TCP_UDP / IP4_OTHER common */
+	[VCAP_IS2_HK_IP4]			= { 46,   1 },
+	[VCAP_IS2_HK_L3_FRAGMENT]		= { 47,   1 },
+	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 48,   1 },
+	[VCAP_IS2_HK_L3_OPTIONS]		= { 49,   1 },
+	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 50,   1 },
+	[VCAP_IS2_HK_L3_TOS]			= { 51,   8 },
+	[VCAP_IS2_HK_L3_IP4_DIP]		= { 59,  32 },
+	[VCAP_IS2_HK_L3_IP4_SIP]		= { 91,  32 },
+	[VCAP_IS2_HK_DIP_EQ_SIP]		= { 123,  1 },
+	/* IP4_TCP_UDP (TYPE=100) */
+	[VCAP_IS2_HK_TCP]			= { 124,  1 },
+	[VCAP_IS2_HK_L4_DPORT]			= { 125, 16 },
+	[VCAP_IS2_HK_L4_SPORT]			= { 141, 16 },
+	[VCAP_IS2_HK_L4_RNG]			= { 157,  8 },
+	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= { 165,  1 },
+	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= { 166,  1 },
+	[VCAP_IS2_HK_L4_FIN]			= { 167,  1 },
+	[VCAP_IS2_HK_L4_SYN]			= { 168,  1 },
+	[VCAP_IS2_HK_L4_RST]			= { 169,  1 },
+	[VCAP_IS2_HK_L4_PSH]			= { 170,  1 },
+	[VCAP_IS2_HK_L4_ACK]			= { 171,  1 },
+	[VCAP_IS2_HK_L4_URG]			= { 172,  1 },
+	[VCAP_IS2_HK_L4_1588_DOM]		= { 173,  8 },
+	[VCAP_IS2_HK_L4_1588_VER]		= { 181,  4 },
+	/* IP4_OTHER (TYPE=101) */
+	[VCAP_IS2_HK_IP4_L3_PROTO]		= { 124,  8 },
+	[VCAP_IS2_HK_L3_PAYLOAD]		= { 132, 56 },
+	/* IP6_STD (TYPE=110) */
+	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 46,   1 },
+	[VCAP_IS2_HK_L3_IP6_SIP]		= { 47, 128 },
+	[VCAP_IS2_HK_IP6_L3_PROTO]		= { 175,  8 },
+	/* OAM (TYPE=111) */
+	[VCAP_IS2_HK_OAM_MEL_FLAGS]		= { 142,  7 },
+	[VCAP_IS2_HK_OAM_VER]			= { 149,  5 },
+	[VCAP_IS2_HK_OAM_OPCODE]		= { 154,  8 },
+	[VCAP_IS2_HK_OAM_FLAGS]			= { 162,  8 },
+	[VCAP_IS2_HK_OAM_MEPID]			= { 170, 16 },
+	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= { 186,  1 },
+	[VCAP_IS2_HK_OAM_IS_Y1731]		= { 187,  1 },
+};
+
+static const struct vcap_field vsc7512_vcap_is2_actions[] = {
+	[VCAP_IS2_ACT_HIT_ME_ONCE]		= { 0,   1 },
+	[VCAP_IS2_ACT_CPU_COPY_ENA]		= { 1,   1 },
+	[VCAP_IS2_ACT_CPU_QU_NUM]		= { 2,   3 },
+	[VCAP_IS2_ACT_MASK_MODE]		= { 5,   2 },
+	[VCAP_IS2_ACT_MIRROR_ENA]		= { 7,   1 },
+	[VCAP_IS2_ACT_LRN_DIS]			= { 8,   1 },
+	[VCAP_IS2_ACT_POLICE_ENA]		= { 9,   1 },
+	[VCAP_IS2_ACT_POLICE_IDX]		= { 10,  9 },
+	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 19,  1 },
+	[VCAP_IS2_ACT_PORT_MASK]		= { 20, 11 },
+	[VCAP_IS2_ACT_REW_OP]			= { 31,  9 },
+	[VCAP_IS2_ACT_SMAC_REPLACE_ENA]		= { 40,  1 },
+	[VCAP_IS2_ACT_RSV]			= { 41,  2 },
+	[VCAP_IS2_ACT_ACL_ID]			= { 43,  6 },
+	[VCAP_IS2_ACT_HIT_CNT]			= { 49, 32 },
+};
+
+static struct vcap_props vsc7512_vcap_props[] = {
+	[VCAP_ES0] = {
+		.action_type_width = 0,
+		.action_table = {
+			[ES0_ACTION_TYPE_NORMAL] = {
+				.width = 73,
+				.count = 1,
+			},
+		},
+		.target = S0,
+		.keys = vsc7512_vcap_es0_keys,
+		.actions = vsc7512_vcap_es0_actions,
+	},
+	[VCAP_IS1] = {
+		.action_type_width = 0,
+		.action_table = {
+			[IS1_ACTION_TYPE_NORMAL] = {
+				.width = 78,
+				.count = 4,
+			},
+		},
+		.target = S1,
+		.keys = vsc7512_vcap_is1_keys,
+		.actions = vsc7512_vcap_is1_actions,
+	},
+	[VCAP_IS2] = {
+		.action_type_width = 1,
+		.action_table = {
+			[IS2_ACTION_TYPE_NORMAL] = {
+				.width = 49,
+				.count = 2,
+			},
+			[IS2_ACTION_TYPE_SMAC_SIP] = {
+				.width = 6,
+				.count = 4,
+			},
+		},
+		.target = S2,
+		.keys = vsc7512_vcap_is2_keys,
+		.actions = vsc7512_vcap_is2_actions,
+	},
+};
+
+static struct regmap *vsc7512_regmap_init(struct ocelot *ocelot,
+					  struct resource *res)
+{
+	struct ocelot_spi_regmap_context *context;
+	struct regmap_config regmap_config;
+	struct ocelot_spi_data *ocelot_spi;
+	struct regmap *regmap;
+	struct device *dev;
+	char name[32];
+
+	ocelot_spi = ocelot_to_ocelot_spi(ocelot);
+	dev = &ocelot_spi->spi->dev;
+
+	context = devm_kzalloc(dev, sizeof(struct ocelot_spi_regmap_context),
+			       GFP_KERNEL);
+
+	if (IS_ERR(context))
+		return ERR_CAST(context);
+
+	context->base = res->start;
+	context->spi = ocelot_spi->spi;
+
+	memcpy(&regmap_config, &ocelot_spi_regmap_config,
+	       sizeof(ocelot_spi_regmap_config));
+
+	/* A unique bus name is required for each regmap */
+	if (res->name)
+		snprintf(name, sizeof(name) - 1, "ocelot_spi-%s", res->name);
+	else
+		snprintf(name, sizeof(name) - 1, "ocelot_spi@0x%08x",
+			 res->start);
+
+	regmap_config.name = name;
+	regmap_config.max_register = res->end - res->start;
+
+	regmap = devm_regmap_init(dev, NULL, context, &regmap_config);
+
+	if (IS_ERR(regmap))
+		return ERR_CAST(regmap);
+
+	return regmap;
+}
+
+/* Code taken from ocelot_adjust_link. Since we don't have a phydev, and
+ * therefore a phydev->link associated with the NPI port, it needs to be enabled
+ * blindly.
+ */
+static void vsc7512_enable_npi_port(struct ocelot *ocelot)
+{
+	struct ocelot_port *npi_port = ocelot->ports[ocelot->npi];
+
+	/* Assuming 1Gbps max speed to the CPU */
+	ocelot_port_writel(npi_port, DEV_MAC_MODE_CFG_FDX_ENA |
+			   OCELOT_SPEED_1000, DEV_MAC_MODE_CFG);
+
+	/* Disable HDX fast control */
+	ocelot_port_writel(npi_port, DEV_PORT_MISC_HDX_FAST_DIS, DEV_PORT_MISC);
+
+	/* Enable SGMII */
+	ocelot_port_writel(npi_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
+			   PCS1G_MODE_CFG);
+	ocelot_port_writel(npi_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
+
+	/* Enable PCS */
+	ocelot_port_writel(npi_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
+
+	/* Disable aneg and loopback */
+	ocelot_port_writel(npi_port, 0, PCS1G_ANEG_CFG);
+	ocelot_port_writel(npi_port, 0, PCS1G_LB_CFG);
+
+	/* Enable MAC module */
+	ocelot_port_writel(npi_port, DEV_MAC_ENA_CFG_RX_ENA |
+			   DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
+
+	/* Take MAC, Port, Phy and PCS clock out of reset */
+	ocelot_port_writel(npi_port,
+			   DEV_CLOCK_CFG_LINK_SPEED(OCELOT_SPEED_1000),
+			   DEV_CLOCK_CFG);
+
+	/* No PFS */
+	ocelot_write_gix(ocelot,
+			 ANA_PFC_PFC_CFG_FC_LINK_SPEED(OCELOT_SPEED_1000),
+			 ANA_PFC_PFC_CFG, ocelot->npi);
+
+	/* Enable port for frame transfer */
+	ocelot_fields_write(ocelot, ocelot->npi,
+			    QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
+
+	/* Flow control */
+	ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
+			SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
+			SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
+			SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
+			SYS_MAC_FC_CFG_FC_LINK_SPEED(OCELOT_SPEED_1000),
+			SYS_MAC_FC_CFG, ocelot->npi);
+	ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, ocelot->npi);
+
+	/* Enable receiving frames on the port, and auto-learning of MAC
+	 * addresses.
+	 */
+	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_LEARNAUTO |
+			ANA_PORT_PORT_CFG_RECV_ENA |
+			ANA_PORT_PORT_CFG_PORTID_VAL(ocelot->npi),
+			ANA_PORT_PORT_CFG, ocelot->npi);
+}
+
+static const struct felix_info ocelot_spi_info = {
+	.target_io_res			= vsc7512_target_io_res,
+	.port_io_res			= vsc7512_port_io_res,
+	.regfields			= vsc7512_regfields,
+	.map				= vsc7512_regmap,
+	.ops				= &vsc7512_ops,
+	.stats_layout			= vsc7512_stats_layout,
+	.num_stats			= ARRAY_SIZE(vsc7512_stats_layout),
+	.vcap				= vsc7512_vcap_props,
+	.num_mact_rows			= 1024,
+	.num_ports			= 11,
+	.num_tx_queues			= OCELOT_NUM_TC,
+	.mdio_bus_alloc			= felix_mdio_bus_alloc,
+	.mdio_bus_free			= felix_mdio_bus_free,
+	.phylink_validate		= vsc7512_phylink_validate,
+	.prevalidate_phy_mode		= vsc7512_prevalidate_phy_mode,
+	.port_setup_tc			= vsc7512_port_setup_tc,
+	.init_regmap			= vsc7512_regmap_init,
+	.enable_npi_port		= vsc7512_enable_npi_port,
+};
+
+static int ocelot_spi_probe(struct spi_device *spi)
+{
+	struct ocelot_spi_data *ocelot_spi;
+	struct dsa_switch *ds;
+	struct ocelot *ocelot;
+	struct felix *felix;
+	struct device *dev;
+	int err;
+
+	dev = &spi->dev;
+
+	ocelot_spi = devm_kzalloc(dev, sizeof(struct ocelot_spi_data),
+				  GFP_KERNEL);
+
+	if (!ocelot_spi)
+		return -ENOMEM;
+
+	if (spi->max_speed_hz <= 500000) {
+		ocelot_spi->spi_padding_bytes = 0;
+	} else {
+		/* Calculation taken from the manual for IF_CFGSTAT:IF_CFG. Err
+		 * on the side of more padding bytes, as having too few can be
+		 * difficult to detect at runtime.
+		 */
+		ocelot_spi->spi_padding_bytes = 1 +
+			(spi->max_speed_hz / 1000000 + 2) / 8;
+	}
+
+	dev_set_drvdata(dev, ocelot_spi);
+	ocelot_spi->spi = spi;
+
+	spi->bits_per_word = 8;
+
+	err = spi_setup(spi);
+	if (err < 0) {
+		dev_err(&spi->dev, "Error %d initializing SPI\n", err);
+		return err;
+	}
+
+	felix = &ocelot_spi->felix;
+
+	ocelot = &felix->ocelot;
+	ocelot->dev = dev;
+
+	ocelot->num_flooding_pgids = 1;
+
+	felix->info = &ocelot_spi_info;
+
+	ds = kzalloc(sizeof(*ds), GFP_KERNEL);
+	if (!ds) {
+		err = -ENOMEM;
+		dev_err(dev, "Failed to allocate DSA switch\n");
+		return err;
+	}
+
+	ds->dev = &spi->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(dev, "Failed to register DSA switch: %d\n", err);
+		goto err_register_ds;
+	}
+
+	return 0;
+
+err_register_ds:
+	kfree(ds);
+	return err;
+}
+
+static int ocelot_spi_remove(struct spi_device *spi)
+{
+	struct ocelot_spi_data *ocelot_spi;
+	struct felix *felix;
+
+	ocelot_spi = spi_get_drvdata(spi);
+	felix = &ocelot_spi->felix;
+
+	dsa_unregister_switch(felix->ds);
+
+	kfree(felix->ds);
+
+	devm_kfree(&spi->dev, ocelot_spi);
+
+	return 0;
+}
+
+const struct of_device_id vsc7512_of_match[] = {
+	{ .compatible = "mscc,vsc7514" },
+	{ .compatible = "mscc,vsc7513" },
+	{ .compatible = "mscc,vsc7512" },
+	{ .compatible = "mscc,vsc7511" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, vsc7512_of_match);
+
+static struct spi_driver ocelot_vsc7512_spi_driver = {
+	.driver = {
+		.name = "vsc7512",
+		.of_match_table = of_match_ptr(vsc7512_of_match),
+	},
+	.probe = ocelot_spi_probe,
+	.remove = ocelot_spi_remove,
+};
+module_spi_driver(ocelot_vsc7512_spi_driver);
+
+MODULE_DESCRIPTION("Ocelot Switch SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index adfb9781799e..10937dc59fce 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2016,6 +2016,14 @@ int ocelot_init(struct ocelot *ocelot)
 	int i, ret;
 	u32 port;
 
+	if (ocelot->ops->bus_init) {
+		ret = ocelot->ops->bus_init(ocelot);
+		if (ret) {
+			dev_err(ocelot->dev, "Bus init failed\n");
+			return ret;
+		}
+	}
+
 	if (ocelot->ops->reset) {
 		ret = ocelot->ops->reset(ocelot);
 		if (ret) {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index ff6e65a266d6..f5383804e724 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -129,6 +129,7 @@ enum ocelot_target {
 	PTP,
 	GCB,
 	DEV_GMII,
+	DEV_CPUORG,
 	TARGET_MAX,
 };
 
@@ -407,6 +408,8 @@ enum ocelot_reg {
 	GCB_MIIM_MII_STATUS,
 	GCB_MIIM_MII_CMD,
 	GCB_MIIM_MII_DATA,
+	GCB_PHY_PHY_CFG,
+	GCB_PHY_PHY_STAT,
 	DEV_CLOCK_CFG = DEV_GMII << TARGET_OFFSET,
 	DEV_PORT_MISC,
 	DEV_EVENTS,
@@ -446,6 +449,20 @@ enum ocelot_reg {
 	PCS1G_TSTPAT_STATUS,
 	DEV_PCS_FX100_CFG,
 	DEV_PCS_FX100_STATUS,
+	DEV_CPUORG_IF_CTRL = DEV_CPUORG << TARGET_OFFSET,
+	DEV_CPUORG_IF_CFGSTAT,
+	DEV_CPUORG_ORG_CFG,
+	DEV_CPUORG_ERR_CNTS,
+	DEV_CPUORG_TIMEOUT_CFG,
+	DEV_CPUORG_GPR,
+	DEV_CPUORG_MAILBOX_SET,
+	DEV_CPUORG_MAILBOX_CLR,
+	DEV_CPUORG_MAILBOX,
+	DEV_CPUORG_SEMA_CFG,
+	DEV_CPUORG_SEMA0,
+	DEV_CPUORG_SEMA0_OWNER,
+	DEV_CPUORG_SEMA1,
+	DEV_CPUORG_SEMA1_OWNER,
 };
 
 enum ocelot_regfield {
@@ -504,6 +521,7 @@ enum ocelot_regfield {
 	SYS_RESET_CFG_MEM_ENA,
 	SYS_RESET_CFG_MEM_INIT,
 	GCB_SOFT_RST_SWC_RST,
+	GCB_SOFT_RST_CHIP_RST,
 	GCB_MIIM_MII_STATUS_PENDING,
 	GCB_MIIM_MII_STATUS_BUSY,
 	SYS_PAUSE_CFG_PAUSE_START,
@@ -560,6 +578,7 @@ struct ocelot;
 struct ocelot_ops {
 	struct net_device *(*port_to_netdev)(struct ocelot *ocelot, int port);
 	int (*netdev_to_port)(struct net_device *dev);
+	int (*bus_init)(struct ocelot *ocelot);
 	int (*reset)(struct ocelot *ocelot);
 	u16 (*wm_enc)(u16 value);
 	u16 (*wm_dec)(u16 value);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
                   ` (8 preceding siblings ...)
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI Colin Foster
@ 2021-08-14  2:50 ` Colin Foster
  2021-08-14 11:47   ` Vladimir Oltean
  2021-08-17 22:08   ` Rob Herring
  9 siblings, 2 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14  2:50 UTC (permalink / raw)
  To: colin.foster, andrew, vivien.didelot, f.fainelli, olteanv, davem,
	kuba, robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, linux
  Cc: netdev, devicetree, linux-kernel

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 .../devicetree/bindings/net/dsa/ocelot.txt    | 92 +++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/ocelot.txt b/Documentation/devicetree/bindings/net/dsa/ocelot.txt
index 7a271d070b72..edf560a50803 100644
--- a/Documentation/devicetree/bindings/net/dsa/ocelot.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ocelot.txt
@@ -8,6 +8,7 @@ Currently the switches supported by the felix driver are:
 
 - VSC9959 (Felix)
 - VSC9953 (Seville)
+- VSC7511, VSC7512, VSC7513, VSC7514 via SPI
 
 The VSC9959 switch is found in the NXP LS1028A. It is a PCI device, part of the
 larger ENETC root complex. As a result, the ethernet-switch node is a sub-node
@@ -211,3 +212,94 @@ Example:
 		};
 	};
 };
+
+The VSC7513 and VSC7514 switches can be controlled internally via the MIPS
+processor. The VSC7511 and VSC7512 don't have this internal processor, but all
+four chips can be controlled externally through SPI with the following required
+properties:
+
+- compatible:
+	Can be "mscc,vsc7511", "mscc,vsc7512", "mscc,vsc7513", or
+	"mscc,vsc7514".
+
+Supported phy modes for all chips are:
+
+* phy_mode = "sgmii": on ports 0, 1, 2, 3
+
+The VSC7512 and 7514 also support:
+
+* phy_mode = "sgmii": on ports 4, 5, 6, 7
+* phy_mode = "qsgmii": on ports 7, 8, 10
+
+Example for control from a BeagleBone Black
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ethernet-switch@0 {
+		compatible = "mscc,vsc7512";
+		spi-max-frequency = <250000>;
+		reg = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				ethernet = <&mac>;
+				phy-mode = "sgmii";
+
+				fixed-link {
+					speed = <100>;
+					full-duplex;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "swp1";
+				phy-handle = <&sw_phy1>;
+				phy-mode = "sgmii";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "swp2";
+				phy-handle = <&sw_phy2>;
+				phy-mode = "sgmii";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "swp3";
+				phy-handle = <&sw_phy3>;
+				phy-mode = "sgmii";
+			};
+		};
+
+		mdio {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			sw_phy1: ethernet-phy@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x1>;
+			};
+
+			sw_phy2: ethernet-phy@2 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x2>;
+			};
+
+			sw_phy3: ethernet-phy@3 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x3>;
+			};
+		};
+	};
+};
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation Colin Foster
@ 2021-08-14 11:03   ` Vladimir Oltean
  2021-08-20 16:53     ` Colin Foster
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 11:03 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:49:55PM -0700, Colin Foster wrote:
> Utilize regmap instead of __iomem to perform indirect mdio access. This
> will allow for custom regmaps to be used by way of the mscc_miim_setup
> function.
> 
> Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> ---

git b4 20210814025003.2449143-1-colin.foster@in-advantage.com
Looking up https://lore.kernel.org/r/20210814025003.2449143-1-colin.foster%40in-advantage.com
Grabbing thread from lore.kernel.org/linux-devicetree/20210814025003.2449143-1-colin.foster%40in-advantage.com/t.mbox.gz
Analyzing 11 messages in the thread
Checking attestation on all messages, may take a moment...
---
  ✓ [PATCH RFC v3 1/10] net: dsa: ocelot: remove unnecessary pci_bar variables
  ✓ [PATCH RFC v3 2/10] net: mdio: mscc-miim: convert to a regmap implementation
  ✓ [PATCH RFC v3 3/10] net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect mdio access
  ✓ [PATCH RFC v3 4/10] net: dsa: ocelot: felix: Remove requirement for PCS in felix devices
  ✓ [PATCH RFC v3 5/10] net: dsa: ocelot: felix: add interface for custom regmaps
  ✓ [PATCH RFC v3 6/10] net: mscc: ocelot: split register definitions to a separate file
  ✓ [PATCH RFC v3 7/10] net: mscc: ocelot: expose ocelot wm functions
  ✓ [PATCH RFC v3 8/10] net: mscc: ocelot: felix: add ability to enable a CPU / NPI port
  ✓ [PATCH RFC v3 9/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  ✓ [PATCH RFC v3 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  ---
  ✓ Signed: DKIM/inadvantage.onmicrosoft.com (From: colin.foster@in-advantage.com)
---
Total patches: 10
---
 Link: https://lore.kernel.org/r/20210814025003.2449143-1-colin.foster@in-advantage.com
 Base: not found
Applying: net: dsa: ocelot: remove unnecessary pci_bar variables
Applying: net: mdio: mscc-miim: convert to a regmap implementation
Using index info to reconstruct a base tree...
M       drivers/net/mdio/mdio-mscc-miim.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/net/mdio/mdio-mscc-miim.c
CONFLICT (content): Merge conflict in drivers/net/mdio/mdio-mscc-miim.c
error: Failed to merge in the changes.
Patch failed at 0002 net: mdio: mscc-miim: convert to a regmap implementation
hint: Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables Colin Foster
@ 2021-08-14 11:07   ` Vladimir Oltean
  2021-08-14 16:26     ` Colin Foster
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 11:07 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:49:54PM -0700, Colin Foster wrote:
> The pci_bar variables for the switch and imdio don't make sense for the
> generic felix driver. Moving them to felix_vsc9959 to limit scope and
> simplify the felix_info struct.
> 
> Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> ---

I distinctly remember giving a Reviewed-by tag for this patch in the
previous series:

https://patchwork.kernel.org/project/netdevbpf/patch/20210710192602.2186370-2-colin.foster@in-advantage.com/

It would be nice if you could carry them along from one series to the
next so we don't have to chase you.

If you use git b4 when you start working on a new version, the extra
tags in the comments are downloaded and appended automatically. That is
if you are not ok with manually copy-pasting them into your commit
message.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file Colin Foster
@ 2021-08-14 11:15   ` Vladimir Oltean
  2021-08-14 16:33     ` Colin Foster
  2021-08-14 16:56   ` Alexandre Belloni
  1 sibling, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 11:15 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:49:59PM -0700, Colin Foster wrote:
> Moving these to a separate file will allow them to be shared to other
> drivers.
> 
> Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> ---

What about the VCAP bit fields?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions Colin Foster
@ 2021-08-14 11:17   ` Vladimir Oltean
  2021-08-14 16:36     ` Colin Foster
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 11:17 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:50:00PM -0700, Colin Foster wrote:
> Expose ocelot_wm functions so they can be shared with other drivers.
> 
> Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> ---

Can these be moved to ocelot_devlink.c? There's a lot of watermark code
already in there.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI Colin Foster
@ 2021-08-14 11:43   ` Vladimir Oltean
  2021-08-14 12:02     ` Vladimir Oltean
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 11:43 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:50:02PM -0700, Colin Foster wrote:
> +/* Code taken from ocelot_adjust_link. Since we don't have a phydev, and
> + * therefore a phydev->link associated with the NPI port, it needs to be enabled
> + * blindly.
> + */

This makes no sense. You do have a phylink associated with the NPI port,
see for yourself, all of felix_phylink_mac_link_up, felix_phylink_mac_config,
felix_phylink_validate get called for the NPI port.

The trouble, really, is that what is done in felix_phylink_mac_link_up
is not sufficient for your hardware. The felix_vsc9959 and seville_vsc9953
drivers are Microchip switches integrated with NXP PCS, and the NXP PCS
has a dedicated driver in drivers/net/pcs/pcs-lynx.c.

So you won't see any of the PCS1G writes in the common driver, because
NXP integrations of these switches don't have that block.

This is not the proper way to do things. You are "fixing" SGMII for the
NPI/CPU port by pretending it's an NPI port issue, but in reality all
the other ports that use SGMII need the same treatment.

What we might need is a dedicated PCS driver for the VSC7512 switch, and
a way for the felix driver to interchangeably work with either struct
lynx_pcs or struct ocelot_pcs (or whatever it's going to be called).

The issue is that the registers for the PCS1G block look nothing like
the MDIO clause 22 layout, so anything that tries to map the struct
ocelot_pcs over a struct mdio_device is going to look like a horrible
shoehorn.

For that we might need Russell's assistance.

The documentation is at:
http://ww1.microchip.com/downloads/en/DeviceDoc/VMDS-10489.pdf
search for "Information about the registers for this product is available in the attached file."
and then open the PDF embedded within the PDF.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device Colin Foster
@ 2021-08-14 11:47   ` Vladimir Oltean
  2021-08-14 18:40     ` Colin Foster
  2021-08-17 22:08   ` Rob Herring
  1 sibling, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 11:47 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:50:03PM -0700, Colin Foster wrote:
> +* phy_mode = "sgmii": on ports 0, 1, 2, 3

> +			port@0 {
> +				reg = <0>;
> +				ethernet = <&mac>;
> +				phy-mode = "sgmii";
> +
> +				fixed-link {
> +					speed = <100>;
> +					full-duplex;
> +				};
> +			};

Your driver is unconditionally setting up the NPI port at gigabit and
you claim it works, yet the device tree sees a 100Mbps fixed-link? Which
one is right, what speed does the port operate at?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-14 11:43   ` Vladimir Oltean
@ 2021-08-14 12:02     ` Vladimir Oltean
  2021-08-15 19:10       ` Colin Foster
                         ` (2 more replies)
  0 siblings, 3 replies; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 12:02 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 02:43:29PM +0300, Vladimir Oltean wrote:
> The issue is that the registers for the PCS1G block look nothing like
> the MDIO clause 22 layout, so anything that tries to map the struct
> ocelot_pcs over a struct mdio_device is going to look like a horrible
> shoehorn.
> 
> For that we might need Russell's assistance.
> 
> The documentation is at:
> http://ww1.microchip.com/downloads/en/DeviceDoc/VMDS-10489.pdf
> search for "Information about the registers for this product is available in the attached file."
> and then open the PDF embedded within the PDF.

In fact I do notice now that as long as you don't use any of the
optional phylink_mii_c22_pcs_* helpers in your PCS driver, then
struct phylink_pcs has pretty much zero dependency on struct mdio_device,
which means that I'm wrong and it should be completely within reach to
write a dedicated PCS driver for this hardware.

As to how to make the common felix.c work with different implementations
of struct phylink_pcs, one thing that certainly has to change is that
struct felix should hold a struct phylink_pcs **pcs and not a
struct lynx_pcs **pcs.

Does this mean that we should refactor lynx_pcs_create() to return a
struct phylink_pcs * instead of struct lynx_pcs *, and lynx_pcs_destroy()
to receive the struct phylink_pcs *, use container_of() and free the
larger struct lynx_pcs *? Yes, probably.

If you feel uncomfortable with this, I can try to refactor lynx_pcs to
make it easier to accomodate a different PCS driver in felix.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables
  2021-08-14 11:07   ` Vladimir Oltean
@ 2021-08-14 16:26     ` Colin Foster
  0 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14 16:26 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 02:07:05PM +0300, Vladimir Oltean wrote:
> On Fri, Aug 13, 2021 at 07:49:54PM -0700, Colin Foster wrote:
> > The pci_bar variables for the switch and imdio don't make sense for the
> > generic felix driver. Moving them to felix_vsc9959 to limit scope and
> > simplify the felix_info struct.
> > 
> > Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> > ---
> 
> I distinctly remember giving a Reviewed-by tag for this patch in the
> previous series:
> 
> https://patchwork.kernel.org/project/netdevbpf/patch/20210710192602.2186370-2-colin.foster@in-advantage.com/
> 
> It would be nice if you could carry them along from one series to the
> next so we don't have to chase you.
> 
> If you use git b4 when you start working on a new version, the extra
> tags in the comments are downloaded and appended automatically. That is
> if you are not ok with manually copy-pasting them into your commit
> message.

Yes, you did. I'll do that next time. Forgive me, for this entire
process is very much a learning experience for me.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file
  2021-08-14 11:15   ` Vladimir Oltean
@ 2021-08-14 16:33     ` Colin Foster
  0 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14 16:33 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 02:15:09PM +0300, Vladimir Oltean wrote:
> On Fri, Aug 13, 2021 at 07:49:59PM -0700, Colin Foster wrote:
> > Moving these to a separate file will allow them to be shared to other
> > drivers.
> > 
> > Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> > ---
> 
> What about the VCAP bit fields?

Good find. I'll break those out and delete my duplicate copies.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions
  2021-08-14 11:17   ` Vladimir Oltean
@ 2021-08-14 16:36     ` Colin Foster
  0 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-14 16:36 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 02:17:01PM +0300, Vladimir Oltean wrote:
> On Fri, Aug 13, 2021 at 07:50:00PM -0700, Colin Foster wrote:
> > Expose ocelot_wm functions so they can be shared with other drivers.
> > 
> > Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> > ---
> 
> Can these be moved to ocelot_devlink.c? There's a lot of watermark code
> already in there.

Yes, that should be easy enough.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file
  2021-08-14  2:49 ` [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file Colin Foster
  2021-08-14 11:15   ` Vladimir Oltean
@ 2021-08-14 16:56   ` Alexandre Belloni
  1 sibling, 0 replies; 36+ messages in thread
From: Alexandre Belloni @ 2021-08-14 16:56 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, olteanv, davem, kuba,
	robh+dt, claudiu.manoil, UNGLinuxDriver, hkallweit1, linux,
	netdev, devicetree, linux-kernel

Hello,

On 13/08/2021 19:49:59-0700, Colin Foster wrote:
> Moving these to a separate file will allow them to be shared to other
> drivers.
> 
> Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> ---
>  drivers/net/ethernet/mscc/Makefile         |   1 +
>  drivers/net/ethernet/mscc/ocelot_regs.c    | 309 +++++++++++++++++++++

Maybe this should be named
drivers/net/ethernet/mscc/ocelot_vsc7514_regs.c in the case we had more
chips later on. The naming we chose is that ocelot refers generically to
the switch IP instead of a specific implementation.

>  drivers/net/ethernet/mscc/ocelot_vsc7514.c | 295 +-------------------
>  include/soc/mscc/ocelot_regs.h             |  20 ++
>  4 files changed, 331 insertions(+), 294 deletions(-)
>  create mode 100644 drivers/net/ethernet/mscc/ocelot_regs.c
>  create mode 100644 include/soc/mscc/ocelot_regs.h
> 
> diff --git a/drivers/net/ethernet/mscc/Makefile b/drivers/net/ethernet/mscc/Makefile
> index 722c27694b21..d539a231a478 100644
> --- a/drivers/net/ethernet/mscc/Makefile
> +++ b/drivers/net/ethernet/mscc/Makefile
> @@ -7,6 +7,7 @@ mscc_ocelot_switch_lib-y := \
>  	ocelot_vcap.o \
>  	ocelot_flower.o \
>  	ocelot_ptp.o \
> +	ocelot_regs.o \
>  	ocelot_devlink.o
>  mscc_ocelot_switch_lib-$(CONFIG_BRIDGE_MRP) += ocelot_mrp.o
>  obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot.o
> diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
> new file mode 100644
> index 000000000000..b7ba137a7c90
> --- /dev/null
> +++ b/drivers/net/ethernet/mscc/ocelot_regs.c
> @@ -0,0 +1,309 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Microsemi Ocelot Switch driver
> + *
> + * Copyright (c) 2017 Microsemi Corporation
> + */
> +#include "ocelot.h"
> +
> +const u32 ocelot_ana_regmap[] = {
> +	REG(ANA_ADVLEARN,				0x009000),
> +	REG(ANA_VLANMASK,				0x009004),
> +	REG(ANA_PORT_B_DOMAIN,				0x009008),
> +	REG(ANA_ANAGEFIL,				0x00900c),
> +	REG(ANA_ANEVENTS,				0x009010),
> +	REG(ANA_STORMLIMIT_BURST,			0x009014),
> +	REG(ANA_STORMLIMIT_CFG,				0x009018),
> +	REG(ANA_ISOLATED_PORTS,				0x009028),
> +	REG(ANA_COMMUNITY_PORTS,			0x00902c),
> +	REG(ANA_AUTOAGE,				0x009030),
> +	REG(ANA_MACTOPTIONS,				0x009034),
> +	REG(ANA_LEARNDISC,				0x009038),
> +	REG(ANA_AGENCTRL,				0x00903c),
> +	REG(ANA_MIRRORPORTS,				0x009040),
> +	REG(ANA_EMIRRORPORTS,				0x009044),
> +	REG(ANA_FLOODING,				0x009048),
> +	REG(ANA_FLOODING_IPMC,				0x00904c),
> +	REG(ANA_SFLOW_CFG,				0x009050),
> +	REG(ANA_PORT_MODE,				0x009080),
> +	REG(ANA_PGID_PGID,				0x008c00),
> +	REG(ANA_TABLES_ANMOVED,				0x008b30),
> +	REG(ANA_TABLES_MACHDATA,			0x008b34),
> +	REG(ANA_TABLES_MACLDATA,			0x008b38),
> +	REG(ANA_TABLES_MACACCESS,			0x008b3c),
> +	REG(ANA_TABLES_MACTINDX,			0x008b40),
> +	REG(ANA_TABLES_VLANACCESS,			0x008b44),
> +	REG(ANA_TABLES_VLANTIDX,			0x008b48),
> +	REG(ANA_TABLES_ISDXACCESS,			0x008b4c),
> +	REG(ANA_TABLES_ISDXTIDX,			0x008b50),
> +	REG(ANA_TABLES_ENTRYLIM,			0x008b00),
> +	REG(ANA_TABLES_PTP_ID_HIGH,			0x008b54),
> +	REG(ANA_TABLES_PTP_ID_LOW,			0x008b58),
> +	REG(ANA_MSTI_STATE,				0x008e00),
> +	REG(ANA_PORT_VLAN_CFG,				0x007000),
> +	REG(ANA_PORT_DROP_CFG,				0x007004),
> +	REG(ANA_PORT_QOS_CFG,				0x007008),
> +	REG(ANA_PORT_VCAP_CFG,				0x00700c),
> +	REG(ANA_PORT_VCAP_S1_KEY_CFG,			0x007010),
> +	REG(ANA_PORT_VCAP_S2_CFG,			0x00701c),
> +	REG(ANA_PORT_PCP_DEI_MAP,			0x007020),
> +	REG(ANA_PORT_CPU_FWD_CFG,			0x007060),
> +	REG(ANA_PORT_CPU_FWD_BPDU_CFG,			0x007064),
> +	REG(ANA_PORT_CPU_FWD_GARP_CFG,			0x007068),
> +	REG(ANA_PORT_CPU_FWD_CCM_CFG,			0x00706c),
> +	REG(ANA_PORT_PORT_CFG,				0x007070),
> +	REG(ANA_PORT_POL_CFG,				0x007074),
> +	REG(ANA_PORT_PTP_CFG,				0x007078),
> +	REG(ANA_PORT_PTP_DLY1_CFG,			0x00707c),
> +	REG(ANA_OAM_UPM_LM_CNT,				0x007c00),
> +	REG(ANA_PORT_PTP_DLY2_CFG,			0x007080),
> +	REG(ANA_PFC_PFC_CFG,				0x008800),
> +	REG(ANA_PFC_PFC_TIMER,				0x008804),
> +	REG(ANA_IPT_OAM_MEP_CFG,			0x008000),
> +	REG(ANA_IPT_IPT,				0x008004),
> +	REG(ANA_PPT_PPT,				0x008ac0),
> +	REG(ANA_FID_MAP_FID_MAP,			0x000000),
> +	REG(ANA_AGGR_CFG,				0x0090b4),
> +	REG(ANA_CPUQ_CFG,				0x0090b8),
> +	REG(ANA_CPUQ_CFG2,				0x0090bc),
> +	REG(ANA_CPUQ_8021_CFG,				0x0090c0),
> +	REG(ANA_DSCP_CFG,				0x009100),
> +	REG(ANA_DSCP_REWR_CFG,				0x009200),
> +	REG(ANA_VCAP_RNG_TYPE_CFG,			0x009240),
> +	REG(ANA_VCAP_RNG_VAL_CFG,			0x009260),
> +	REG(ANA_VRAP_CFG,				0x009280),
> +	REG(ANA_VRAP_HDR_DATA,				0x009284),
> +	REG(ANA_VRAP_HDR_MASK,				0x009288),
> +	REG(ANA_DISCARD_CFG,				0x00928c),
> +	REG(ANA_FID_CFG,				0x009290),
> +	REG(ANA_POL_PIR_CFG,				0x004000),
> +	REG(ANA_POL_CIR_CFG,				0x004004),
> +	REG(ANA_POL_MODE_CFG,				0x004008),
> +	REG(ANA_POL_PIR_STATE,				0x00400c),
> +	REG(ANA_POL_CIR_STATE,				0x004010),
> +	REG(ANA_POL_STATE,				0x004014),
> +	REG(ANA_POL_FLOWC,				0x008b80),
> +	REG(ANA_POL_HYST,				0x008bec),
> +	REG(ANA_POL_MISC_CFG,				0x008bf0),
> +};
> +EXPORT_SYMBOL(ocelot_ana_regmap);
> +
> +const u32 ocelot_qs_regmap[] = {
> +	REG(QS_XTR_GRP_CFG,				0x000000),
> +	REG(QS_XTR_RD,					0x000008),
> +	REG(QS_XTR_FRM_PRUNING,				0x000010),
> +	REG(QS_XTR_FLUSH,				0x000018),
> +	REG(QS_XTR_DATA_PRESENT,			0x00001c),
> +	REG(QS_XTR_CFG,					0x000020),
> +	REG(QS_INJ_GRP_CFG,				0x000024),
> +	REG(QS_INJ_WR,					0x00002c),
> +	REG(QS_INJ_CTRL,				0x000034),
> +	REG(QS_INJ_STATUS,				0x00003c),
> +	REG(QS_INJ_ERR,					0x000040),
> +	REG(QS_INH_DBG,					0x000048),
> +};
> +EXPORT_SYMBOL(ocelot_qs_regmap);
> +
> +const u32 ocelot_qsys_regmap[] = {
> +	REG(QSYS_PORT_MODE,				0x011200),
> +	REG(QSYS_SWITCH_PORT_MODE,			0x011234),
> +	REG(QSYS_STAT_CNT_CFG,				0x011264),
> +	REG(QSYS_EEE_CFG,				0x011268),
> +	REG(QSYS_EEE_THRES,				0x011294),
> +	REG(QSYS_IGR_NO_SHARING,			0x011298),
> +	REG(QSYS_EGR_NO_SHARING,			0x01129c),
> +	REG(QSYS_SW_STATUS,				0x0112a0),
> +	REG(QSYS_EXT_CPU_CFG,				0x0112d0),
> +	REG(QSYS_PAD_CFG,				0x0112d4),
> +	REG(QSYS_CPU_GROUP_MAP,				0x0112d8),
> +	REG(QSYS_QMAP,					0x0112dc),
> +	REG(QSYS_ISDX_SGRP,				0x011400),
> +	REG(QSYS_TIMED_FRAME_ENTRY,			0x014000),
> +	REG(QSYS_TFRM_MISC,				0x011310),
> +	REG(QSYS_TFRM_PORT_DLY,				0x011314),
> +	REG(QSYS_TFRM_TIMER_CFG_1,			0x011318),
> +	REG(QSYS_TFRM_TIMER_CFG_2,			0x01131c),
> +	REG(QSYS_TFRM_TIMER_CFG_3,			0x011320),
> +	REG(QSYS_TFRM_TIMER_CFG_4,			0x011324),
> +	REG(QSYS_TFRM_TIMER_CFG_5,			0x011328),
> +	REG(QSYS_TFRM_TIMER_CFG_6,			0x01132c),
> +	REG(QSYS_TFRM_TIMER_CFG_7,			0x011330),
> +	REG(QSYS_TFRM_TIMER_CFG_8,			0x011334),
> +	REG(QSYS_RED_PROFILE,				0x011338),
> +	REG(QSYS_RES_QOS_MODE,				0x011378),
> +	REG(QSYS_RES_CFG,				0x012000),
> +	REG(QSYS_RES_STAT,				0x012004),
> +	REG(QSYS_EGR_DROP_MODE,				0x01137c),
> +	REG(QSYS_EQ_CTRL,				0x011380),
> +	REG(QSYS_EVENTS_CORE,				0x011384),
> +	REG(QSYS_CIR_CFG,				0x000000),
> +	REG(QSYS_EIR_CFG,				0x000004),
> +	REG(QSYS_SE_CFG,				0x000008),
> +	REG(QSYS_SE_DWRR_CFG,				0x00000c),
> +	REG(QSYS_SE_CONNECT,				0x00003c),
> +	REG(QSYS_SE_DLB_SENSE,				0x000040),
> +	REG(QSYS_CIR_STATE,				0x000044),
> +	REG(QSYS_EIR_STATE,				0x000048),
> +	REG(QSYS_SE_STATE,				0x00004c),
> +	REG(QSYS_HSCH_MISC_CFG,				0x011388),
> +};
> +EXPORT_SYMBOL(ocelot_qsys_regmap);
> +
> +const u32 ocelot_rew_regmap[] = {
> +	REG(REW_PORT_VLAN_CFG,				0x000000),
> +	REG(REW_TAG_CFG,				0x000004),
> +	REG(REW_PORT_CFG,				0x000008),
> +	REG(REW_DSCP_CFG,				0x00000c),
> +	REG(REW_PCP_DEI_QOS_MAP_CFG,			0x000010),
> +	REG(REW_PTP_CFG,				0x000050),
> +	REG(REW_PTP_DLY1_CFG,				0x000054),
> +	REG(REW_DSCP_REMAP_DP1_CFG,			0x000690),
> +	REG(REW_DSCP_REMAP_CFG,				0x000790),
> +	REG(REW_STAT_CFG,				0x000890),
> +	REG(REW_PPT,					0x000680),
> +};
> +EXPORT_SYMBOL(ocelot_rew_regmap);
> +
> +const u32 ocelot_sys_regmap[] = {
> +	REG(SYS_COUNT_RX_OCTETS,			0x000000),
> +	REG(SYS_COUNT_RX_UNICAST,			0x000004),
> +	REG(SYS_COUNT_RX_MULTICAST,			0x000008),
> +	REG(SYS_COUNT_RX_BROADCAST,			0x00000c),
> +	REG(SYS_COUNT_RX_SHORTS,			0x000010),
> +	REG(SYS_COUNT_RX_FRAGMENTS,			0x000014),
> +	REG(SYS_COUNT_RX_JABBERS,			0x000018),
> +	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,		0x00001c),
> +	REG(SYS_COUNT_RX_SYM_ERRS,			0x000020),
> +	REG(SYS_COUNT_RX_64,				0x000024),
> +	REG(SYS_COUNT_RX_65_127,			0x000028),
> +	REG(SYS_COUNT_RX_128_255,			0x00002c),
> +	REG(SYS_COUNT_RX_256_1023,			0x000030),
> +	REG(SYS_COUNT_RX_1024_1526,			0x000034),
> +	REG(SYS_COUNT_RX_1527_MAX,			0x000038),
> +	REG(SYS_COUNT_RX_PAUSE,				0x00003c),
> +	REG(SYS_COUNT_RX_CONTROL,			0x000040),
> +	REG(SYS_COUNT_RX_LONGS,				0x000044),
> +	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x000048),
> +	REG(SYS_COUNT_TX_OCTETS,			0x000100),
> +	REG(SYS_COUNT_TX_UNICAST,			0x000104),
> +	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
> +	REG(SYS_COUNT_TX_BROADCAST,			0x00010c),
> +	REG(SYS_COUNT_TX_COLLISION,			0x000110),
> +	REG(SYS_COUNT_TX_DROPS,				0x000114),
> +	REG(SYS_COUNT_TX_PAUSE,				0x000118),
> +	REG(SYS_COUNT_TX_64,				0x00011c),
> +	REG(SYS_COUNT_TX_65_127,			0x000120),
> +	REG(SYS_COUNT_TX_128_511,			0x000124),
> +	REG(SYS_COUNT_TX_512_1023,			0x000128),
> +	REG(SYS_COUNT_TX_1024_1526,			0x00012c),
> +	REG(SYS_COUNT_TX_1527_MAX,			0x000130),
> +	REG(SYS_COUNT_TX_AGING,				0x000170),
> +	REG(SYS_RESET_CFG,				0x000508),
> +	REG(SYS_CMID,					0x00050c),
> +	REG(SYS_VLAN_ETYPE_CFG,				0x000510),
> +	REG(SYS_PORT_MODE,				0x000514),
> +	REG(SYS_FRONT_PORT_MODE,			0x000548),
> +	REG(SYS_FRM_AGING,				0x000574),
> +	REG(SYS_STAT_CFG,				0x000578),
> +	REG(SYS_SW_STATUS,				0x00057c),
> +	REG(SYS_MISC_CFG,				0x0005ac),
> +	REG(SYS_REW_MAC_HIGH_CFG,			0x0005b0),
> +	REG(SYS_REW_MAC_LOW_CFG,			0x0005dc),
> +	REG(SYS_CM_ADDR,				0x000500),
> +	REG(SYS_CM_DATA,				0x000504),
> +	REG(SYS_PAUSE_CFG,				0x000608),
> +	REG(SYS_PAUSE_TOT_CFG,				0x000638),
> +	REG(SYS_ATOP,					0x00063c),
> +	REG(SYS_ATOP_TOT_CFG,				0x00066c),
> +	REG(SYS_MAC_FC_CFG,				0x000670),
> +	REG(SYS_MMGT,					0x00069c),
> +	REG(SYS_MMGT_FAST,				0x0006a0),
> +	REG(SYS_EVENTS_DIF,				0x0006a4),
> +	REG(SYS_EVENTS_CORE,				0x0006b4),
> +	REG(SYS_CNT,					0x000000),
> +	REG(SYS_PTP_STATUS,				0x0006b8),
> +	REG(SYS_PTP_TXSTAMP,				0x0006bc),
> +	REG(SYS_PTP_NXT,				0x0006c0),
> +	REG(SYS_PTP_CFG,				0x0006c4),
> +};
> +EXPORT_SYMBOL(ocelot_sys_regmap);
> +
> +const u32 ocelot_vcap_regmap[] = {
> +	/* VCAP_CORE_CFG */
> +	REG(VCAP_CORE_UPDATE_CTRL,			0x000000),
> +	REG(VCAP_CORE_MV_CFG,				0x000004),
> +	/* VCAP_CORE_CACHE */
> +	REG(VCAP_CACHE_ENTRY_DAT,			0x000008),
> +	REG(VCAP_CACHE_MASK_DAT,			0x000108),
> +	REG(VCAP_CACHE_ACTION_DAT,			0x000208),
> +	REG(VCAP_CACHE_CNT_DAT,				0x000308),
> +	REG(VCAP_CACHE_TG_DAT,				0x000388),
> +	/* VCAP_CONST */
> +	REG(VCAP_CONST_VCAP_VER,			0x000398),
> +	REG(VCAP_CONST_ENTRY_WIDTH,			0x00039c),
> +	REG(VCAP_CONST_ENTRY_CNT,			0x0003a0),
> +	REG(VCAP_CONST_ENTRY_SWCNT,			0x0003a4),
> +	REG(VCAP_CONST_ENTRY_TG_WIDTH,			0x0003a8),
> +	REG(VCAP_CONST_ACTION_DEF_CNT,			0x0003ac),
> +	REG(VCAP_CONST_ACTION_WIDTH,			0x0003b0),
> +	REG(VCAP_CONST_CNT_WIDTH,			0x0003b4),
> +	REG(VCAP_CONST_CORE_CNT,			0x0003b8),
> +	REG(VCAP_CONST_IF_CNT,				0x0003bc),
> +};
> +EXPORT_SYMBOL(ocelot_vcap_regmap);
> +
> +const u32 ocelot_ptp_regmap[] = {
> +	REG(PTP_PIN_CFG,				0x000000),
> +	REG(PTP_PIN_TOD_SEC_MSB,			0x000004),
> +	REG(PTP_PIN_TOD_SEC_LSB,			0x000008),
> +	REG(PTP_PIN_TOD_NSEC,				0x00000c),
> +	REG(PTP_PIN_WF_HIGH_PERIOD,			0x000014),
> +	REG(PTP_PIN_WF_LOW_PERIOD,			0x000018),
> +	REG(PTP_CFG_MISC,				0x0000a0),
> +	REG(PTP_CLK_CFG_ADJ_CFG,			0x0000a4),
> +	REG(PTP_CLK_CFG_ADJ_FREQ,			0x0000a8),
> +};
> +EXPORT_SYMBOL(ocelot_ptp_regmap);
> +
> +const u32 ocelot_dev_gmii_regmap[] = {
> +	REG(DEV_CLOCK_CFG,				0x0),
> +	REG(DEV_PORT_MISC,				0x4),
> +	REG(DEV_EVENTS,					0x8),
> +	REG(DEV_EEE_CFG,				0xc),
> +	REG(DEV_RX_PATH_DELAY,				0x10),
> +	REG(DEV_TX_PATH_DELAY,				0x14),
> +	REG(DEV_PTP_PREDICT_CFG,			0x18),
> +	REG(DEV_MAC_ENA_CFG,				0x1c),
> +	REG(DEV_MAC_MODE_CFG,				0x20),
> +	REG(DEV_MAC_MAXLEN_CFG,				0x24),
> +	REG(DEV_MAC_TAGS_CFG,				0x28),
> +	REG(DEV_MAC_ADV_CHK_CFG,			0x2c),
> +	REG(DEV_MAC_IFG_CFG,				0x30),
> +	REG(DEV_MAC_HDX_CFG,				0x34),
> +	REG(DEV_MAC_DBG_CFG,				0x38),
> +	REG(DEV_MAC_FC_MAC_LOW_CFG,			0x3c),
> +	REG(DEV_MAC_FC_MAC_HIGH_CFG,			0x40),
> +	REG(DEV_MAC_STICKY,				0x44),
> +	REG(PCS1G_CFG,					0x48),
> +	REG(PCS1G_MODE_CFG,				0x4c),
> +	REG(PCS1G_SD_CFG,				0x50),
> +	REG(PCS1G_ANEG_CFG,				0x54),
> +	REG(PCS1G_ANEG_NP_CFG,				0x58),
> +	REG(PCS1G_LB_CFG,				0x5c),
> +	REG(PCS1G_DBG_CFG,				0x60),
> +	REG(PCS1G_CDET_CFG,				0x64),
> +	REG(PCS1G_ANEG_STATUS,				0x68),
> +	REG(PCS1G_ANEG_NP_STATUS,			0x6c),
> +	REG(PCS1G_LINK_STATUS,				0x70),
> +	REG(PCS1G_LINK_DOWN_CNT,			0x74),
> +	REG(PCS1G_STICKY,				0x78),
> +	REG(PCS1G_DEBUG_STATUS,				0x7c),
> +	REG(PCS1G_LPI_CFG,				0x80),
> +	REG(PCS1G_LPI_WAKE_ERROR_CNT,			0x84),
> +	REG(PCS1G_LPI_STATUS,				0x88),
> +	REG(PCS1G_TSTPAT_MODE_CFG,			0x8c),
> +	REG(PCS1G_TSTPAT_STATUS,			0x90),
> +	REG(DEV_PCS_FX100_CFG,				0x94),
> +	REG(DEV_PCS_FX100_STATUS,			0x98),
> +};
> +EXPORT_SYMBOL(ocelot_dev_gmii_regmap);
> diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
> index 4bd7e9d9ec61..ef1bf24f51b5 100644
> --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
> +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
> @@ -16,303 +16,10 @@
>  #include <net/switchdev.h>
>  
>  #include <soc/mscc/ocelot_vcap.h>
> +#include <soc/mscc/ocelot_regs.h>
>  #include <soc/mscc/ocelot_hsio.h>
>  #include "ocelot.h"
>  
> -static const u32 ocelot_ana_regmap[] = {
> -	REG(ANA_ADVLEARN,				0x009000),
> -	REG(ANA_VLANMASK,				0x009004),
> -	REG(ANA_PORT_B_DOMAIN,				0x009008),
> -	REG(ANA_ANAGEFIL,				0x00900c),
> -	REG(ANA_ANEVENTS,				0x009010),
> -	REG(ANA_STORMLIMIT_BURST,			0x009014),
> -	REG(ANA_STORMLIMIT_CFG,				0x009018),
> -	REG(ANA_ISOLATED_PORTS,				0x009028),
> -	REG(ANA_COMMUNITY_PORTS,			0x00902c),
> -	REG(ANA_AUTOAGE,				0x009030),
> -	REG(ANA_MACTOPTIONS,				0x009034),
> -	REG(ANA_LEARNDISC,				0x009038),
> -	REG(ANA_AGENCTRL,				0x00903c),
> -	REG(ANA_MIRRORPORTS,				0x009040),
> -	REG(ANA_EMIRRORPORTS,				0x009044),
> -	REG(ANA_FLOODING,				0x009048),
> -	REG(ANA_FLOODING_IPMC,				0x00904c),
> -	REG(ANA_SFLOW_CFG,				0x009050),
> -	REG(ANA_PORT_MODE,				0x009080),
> -	REG(ANA_PGID_PGID,				0x008c00),
> -	REG(ANA_TABLES_ANMOVED,				0x008b30),
> -	REG(ANA_TABLES_MACHDATA,			0x008b34),
> -	REG(ANA_TABLES_MACLDATA,			0x008b38),
> -	REG(ANA_TABLES_MACACCESS,			0x008b3c),
> -	REG(ANA_TABLES_MACTINDX,			0x008b40),
> -	REG(ANA_TABLES_VLANACCESS,			0x008b44),
> -	REG(ANA_TABLES_VLANTIDX,			0x008b48),
> -	REG(ANA_TABLES_ISDXACCESS,			0x008b4c),
> -	REG(ANA_TABLES_ISDXTIDX,			0x008b50),
> -	REG(ANA_TABLES_ENTRYLIM,			0x008b00),
> -	REG(ANA_TABLES_PTP_ID_HIGH,			0x008b54),
> -	REG(ANA_TABLES_PTP_ID_LOW,			0x008b58),
> -	REG(ANA_MSTI_STATE,				0x008e00),
> -	REG(ANA_PORT_VLAN_CFG,				0x007000),
> -	REG(ANA_PORT_DROP_CFG,				0x007004),
> -	REG(ANA_PORT_QOS_CFG,				0x007008),
> -	REG(ANA_PORT_VCAP_CFG,				0x00700c),
> -	REG(ANA_PORT_VCAP_S1_KEY_CFG,			0x007010),
> -	REG(ANA_PORT_VCAP_S2_CFG,			0x00701c),
> -	REG(ANA_PORT_PCP_DEI_MAP,			0x007020),
> -	REG(ANA_PORT_CPU_FWD_CFG,			0x007060),
> -	REG(ANA_PORT_CPU_FWD_BPDU_CFG,			0x007064),
> -	REG(ANA_PORT_CPU_FWD_GARP_CFG,			0x007068),
> -	REG(ANA_PORT_CPU_FWD_CCM_CFG,			0x00706c),
> -	REG(ANA_PORT_PORT_CFG,				0x007070),
> -	REG(ANA_PORT_POL_CFG,				0x007074),
> -	REG(ANA_PORT_PTP_CFG,				0x007078),
> -	REG(ANA_PORT_PTP_DLY1_CFG,			0x00707c),
> -	REG(ANA_OAM_UPM_LM_CNT,				0x007c00),
> -	REG(ANA_PORT_PTP_DLY2_CFG,			0x007080),
> -	REG(ANA_PFC_PFC_CFG,				0x008800),
> -	REG(ANA_PFC_PFC_TIMER,				0x008804),
> -	REG(ANA_IPT_OAM_MEP_CFG,			0x008000),
> -	REG(ANA_IPT_IPT,				0x008004),
> -	REG(ANA_PPT_PPT,				0x008ac0),
> -	REG(ANA_FID_MAP_FID_MAP,			0x000000),
> -	REG(ANA_AGGR_CFG,				0x0090b4),
> -	REG(ANA_CPUQ_CFG,				0x0090b8),
> -	REG(ANA_CPUQ_CFG2,				0x0090bc),
> -	REG(ANA_CPUQ_8021_CFG,				0x0090c0),
> -	REG(ANA_DSCP_CFG,				0x009100),
> -	REG(ANA_DSCP_REWR_CFG,				0x009200),
> -	REG(ANA_VCAP_RNG_TYPE_CFG,			0x009240),
> -	REG(ANA_VCAP_RNG_VAL_CFG,			0x009260),
> -	REG(ANA_VRAP_CFG,				0x009280),
> -	REG(ANA_VRAP_HDR_DATA,				0x009284),
> -	REG(ANA_VRAP_HDR_MASK,				0x009288),
> -	REG(ANA_DISCARD_CFG,				0x00928c),
> -	REG(ANA_FID_CFG,				0x009290),
> -	REG(ANA_POL_PIR_CFG,				0x004000),
> -	REG(ANA_POL_CIR_CFG,				0x004004),
> -	REG(ANA_POL_MODE_CFG,				0x004008),
> -	REG(ANA_POL_PIR_STATE,				0x00400c),
> -	REG(ANA_POL_CIR_STATE,				0x004010),
> -	REG(ANA_POL_STATE,				0x004014),
> -	REG(ANA_POL_FLOWC,				0x008b80),
> -	REG(ANA_POL_HYST,				0x008bec),
> -	REG(ANA_POL_MISC_CFG,				0x008bf0),
> -};
> -
> -static const u32 ocelot_qs_regmap[] = {
> -	REG(QS_XTR_GRP_CFG,				0x000000),
> -	REG(QS_XTR_RD,					0x000008),
> -	REG(QS_XTR_FRM_PRUNING,				0x000010),
> -	REG(QS_XTR_FLUSH,				0x000018),
> -	REG(QS_XTR_DATA_PRESENT,			0x00001c),
> -	REG(QS_XTR_CFG,					0x000020),
> -	REG(QS_INJ_GRP_CFG,				0x000024),
> -	REG(QS_INJ_WR,					0x00002c),
> -	REG(QS_INJ_CTRL,				0x000034),
> -	REG(QS_INJ_STATUS,				0x00003c),
> -	REG(QS_INJ_ERR,					0x000040),
> -	REG(QS_INH_DBG,					0x000048),
> -};
> -
> -static const u32 ocelot_qsys_regmap[] = {
> -	REG(QSYS_PORT_MODE,				0x011200),
> -	REG(QSYS_SWITCH_PORT_MODE,			0x011234),
> -	REG(QSYS_STAT_CNT_CFG,				0x011264),
> -	REG(QSYS_EEE_CFG,				0x011268),
> -	REG(QSYS_EEE_THRES,				0x011294),
> -	REG(QSYS_IGR_NO_SHARING,			0x011298),
> -	REG(QSYS_EGR_NO_SHARING,			0x01129c),
> -	REG(QSYS_SW_STATUS,				0x0112a0),
> -	REG(QSYS_EXT_CPU_CFG,				0x0112d0),
> -	REG(QSYS_PAD_CFG,				0x0112d4),
> -	REG(QSYS_CPU_GROUP_MAP,				0x0112d8),
> -	REG(QSYS_QMAP,					0x0112dc),
> -	REG(QSYS_ISDX_SGRP,				0x011400),
> -	REG(QSYS_TIMED_FRAME_ENTRY,			0x014000),
> -	REG(QSYS_TFRM_MISC,				0x011310),
> -	REG(QSYS_TFRM_PORT_DLY,				0x011314),
> -	REG(QSYS_TFRM_TIMER_CFG_1,			0x011318),
> -	REG(QSYS_TFRM_TIMER_CFG_2,			0x01131c),
> -	REG(QSYS_TFRM_TIMER_CFG_3,			0x011320),
> -	REG(QSYS_TFRM_TIMER_CFG_4,			0x011324),
> -	REG(QSYS_TFRM_TIMER_CFG_5,			0x011328),
> -	REG(QSYS_TFRM_TIMER_CFG_6,			0x01132c),
> -	REG(QSYS_TFRM_TIMER_CFG_7,			0x011330),
> -	REG(QSYS_TFRM_TIMER_CFG_8,			0x011334),
> -	REG(QSYS_RED_PROFILE,				0x011338),
> -	REG(QSYS_RES_QOS_MODE,				0x011378),
> -	REG(QSYS_RES_CFG,				0x012000),
> -	REG(QSYS_RES_STAT,				0x012004),
> -	REG(QSYS_EGR_DROP_MODE,				0x01137c),
> -	REG(QSYS_EQ_CTRL,				0x011380),
> -	REG(QSYS_EVENTS_CORE,				0x011384),
> -	REG(QSYS_CIR_CFG,				0x000000),
> -	REG(QSYS_EIR_CFG,				0x000004),
> -	REG(QSYS_SE_CFG,				0x000008),
> -	REG(QSYS_SE_DWRR_CFG,				0x00000c),
> -	REG(QSYS_SE_CONNECT,				0x00003c),
> -	REG(QSYS_SE_DLB_SENSE,				0x000040),
> -	REG(QSYS_CIR_STATE,				0x000044),
> -	REG(QSYS_EIR_STATE,				0x000048),
> -	REG(QSYS_SE_STATE,				0x00004c),
> -	REG(QSYS_HSCH_MISC_CFG,				0x011388),
> -};
> -
> -static const u32 ocelot_rew_regmap[] = {
> -	REG(REW_PORT_VLAN_CFG,				0x000000),
> -	REG(REW_TAG_CFG,				0x000004),
> -	REG(REW_PORT_CFG,				0x000008),
> -	REG(REW_DSCP_CFG,				0x00000c),
> -	REG(REW_PCP_DEI_QOS_MAP_CFG,			0x000010),
> -	REG(REW_PTP_CFG,				0x000050),
> -	REG(REW_PTP_DLY1_CFG,				0x000054),
> -	REG(REW_DSCP_REMAP_DP1_CFG,			0x000690),
> -	REG(REW_DSCP_REMAP_CFG,				0x000790),
> -	REG(REW_STAT_CFG,				0x000890),
> -	REG(REW_PPT,					0x000680),
> -};
> -
> -static const u32 ocelot_sys_regmap[] = {
> -	REG(SYS_COUNT_RX_OCTETS,			0x000000),
> -	REG(SYS_COUNT_RX_UNICAST,			0x000004),
> -	REG(SYS_COUNT_RX_MULTICAST,			0x000008),
> -	REG(SYS_COUNT_RX_BROADCAST,			0x00000c),
> -	REG(SYS_COUNT_RX_SHORTS,			0x000010),
> -	REG(SYS_COUNT_RX_FRAGMENTS,			0x000014),
> -	REG(SYS_COUNT_RX_JABBERS,			0x000018),
> -	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,		0x00001c),
> -	REG(SYS_COUNT_RX_SYM_ERRS,			0x000020),
> -	REG(SYS_COUNT_RX_64,				0x000024),
> -	REG(SYS_COUNT_RX_65_127,			0x000028),
> -	REG(SYS_COUNT_RX_128_255,			0x00002c),
> -	REG(SYS_COUNT_RX_256_1023,			0x000030),
> -	REG(SYS_COUNT_RX_1024_1526,			0x000034),
> -	REG(SYS_COUNT_RX_1527_MAX,			0x000038),
> -	REG(SYS_COUNT_RX_PAUSE,				0x00003c),
> -	REG(SYS_COUNT_RX_CONTROL,			0x000040),
> -	REG(SYS_COUNT_RX_LONGS,				0x000044),
> -	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,		0x000048),
> -	REG(SYS_COUNT_TX_OCTETS,			0x000100),
> -	REG(SYS_COUNT_TX_UNICAST,			0x000104),
> -	REG(SYS_COUNT_TX_MULTICAST,			0x000108),
> -	REG(SYS_COUNT_TX_BROADCAST,			0x00010c),
> -	REG(SYS_COUNT_TX_COLLISION,			0x000110),
> -	REG(SYS_COUNT_TX_DROPS,				0x000114),
> -	REG(SYS_COUNT_TX_PAUSE,				0x000118),
> -	REG(SYS_COUNT_TX_64,				0x00011c),
> -	REG(SYS_COUNT_TX_65_127,			0x000120),
> -	REG(SYS_COUNT_TX_128_511,			0x000124),
> -	REG(SYS_COUNT_TX_512_1023,			0x000128),
> -	REG(SYS_COUNT_TX_1024_1526,			0x00012c),
> -	REG(SYS_COUNT_TX_1527_MAX,			0x000130),
> -	REG(SYS_COUNT_TX_AGING,				0x000170),
> -	REG(SYS_RESET_CFG,				0x000508),
> -	REG(SYS_CMID,					0x00050c),
> -	REG(SYS_VLAN_ETYPE_CFG,				0x000510),
> -	REG(SYS_PORT_MODE,				0x000514),
> -	REG(SYS_FRONT_PORT_MODE,			0x000548),
> -	REG(SYS_FRM_AGING,				0x000574),
> -	REG(SYS_STAT_CFG,				0x000578),
> -	REG(SYS_SW_STATUS,				0x00057c),
> -	REG(SYS_MISC_CFG,				0x0005ac),
> -	REG(SYS_REW_MAC_HIGH_CFG,			0x0005b0),
> -	REG(SYS_REW_MAC_LOW_CFG,			0x0005dc),
> -	REG(SYS_CM_ADDR,				0x000500),
> -	REG(SYS_CM_DATA,				0x000504),
> -	REG(SYS_PAUSE_CFG,				0x000608),
> -	REG(SYS_PAUSE_TOT_CFG,				0x000638),
> -	REG(SYS_ATOP,					0x00063c),
> -	REG(SYS_ATOP_TOT_CFG,				0x00066c),
> -	REG(SYS_MAC_FC_CFG,				0x000670),
> -	REG(SYS_MMGT,					0x00069c),
> -	REG(SYS_MMGT_FAST,				0x0006a0),
> -	REG(SYS_EVENTS_DIF,				0x0006a4),
> -	REG(SYS_EVENTS_CORE,				0x0006b4),
> -	REG(SYS_CNT,					0x000000),
> -	REG(SYS_PTP_STATUS,				0x0006b8),
> -	REG(SYS_PTP_TXSTAMP,				0x0006bc),
> -	REG(SYS_PTP_NXT,				0x0006c0),
> -	REG(SYS_PTP_CFG,				0x0006c4),
> -};
> -
> -static const u32 ocelot_vcap_regmap[] = {
> -	/* VCAP_CORE_CFG */
> -	REG(VCAP_CORE_UPDATE_CTRL,			0x000000),
> -	REG(VCAP_CORE_MV_CFG,				0x000004),
> -	/* VCAP_CORE_CACHE */
> -	REG(VCAP_CACHE_ENTRY_DAT,			0x000008),
> -	REG(VCAP_CACHE_MASK_DAT,			0x000108),
> -	REG(VCAP_CACHE_ACTION_DAT,			0x000208),
> -	REG(VCAP_CACHE_CNT_DAT,				0x000308),
> -	REG(VCAP_CACHE_TG_DAT,				0x000388),
> -	/* VCAP_CONST */
> -	REG(VCAP_CONST_VCAP_VER,			0x000398),
> -	REG(VCAP_CONST_ENTRY_WIDTH,			0x00039c),
> -	REG(VCAP_CONST_ENTRY_CNT,			0x0003a0),
> -	REG(VCAP_CONST_ENTRY_SWCNT,			0x0003a4),
> -	REG(VCAP_CONST_ENTRY_TG_WIDTH,			0x0003a8),
> -	REG(VCAP_CONST_ACTION_DEF_CNT,			0x0003ac),
> -	REG(VCAP_CONST_ACTION_WIDTH,			0x0003b0),
> -	REG(VCAP_CONST_CNT_WIDTH,			0x0003b4),
> -	REG(VCAP_CONST_CORE_CNT,			0x0003b8),
> -	REG(VCAP_CONST_IF_CNT,				0x0003bc),
> -};
> -
> -static const u32 ocelot_ptp_regmap[] = {
> -	REG(PTP_PIN_CFG,				0x000000),
> -	REG(PTP_PIN_TOD_SEC_MSB,			0x000004),
> -	REG(PTP_PIN_TOD_SEC_LSB,			0x000008),
> -	REG(PTP_PIN_TOD_NSEC,				0x00000c),
> -	REG(PTP_PIN_WF_HIGH_PERIOD,			0x000014),
> -	REG(PTP_PIN_WF_LOW_PERIOD,			0x000018),
> -	REG(PTP_CFG_MISC,				0x0000a0),
> -	REG(PTP_CLK_CFG_ADJ_CFG,			0x0000a4),
> -	REG(PTP_CLK_CFG_ADJ_FREQ,			0x0000a8),
> -};
> -
> -static const u32 ocelot_dev_gmii_regmap[] = {
> -	REG(DEV_CLOCK_CFG,				0x0),
> -	REG(DEV_PORT_MISC,				0x4),
> -	REG(DEV_EVENTS,					0x8),
> -	REG(DEV_EEE_CFG,				0xc),
> -	REG(DEV_RX_PATH_DELAY,				0x10),
> -	REG(DEV_TX_PATH_DELAY,				0x14),
> -	REG(DEV_PTP_PREDICT_CFG,			0x18),
> -	REG(DEV_MAC_ENA_CFG,				0x1c),
> -	REG(DEV_MAC_MODE_CFG,				0x20),
> -	REG(DEV_MAC_MAXLEN_CFG,				0x24),
> -	REG(DEV_MAC_TAGS_CFG,				0x28),
> -	REG(DEV_MAC_ADV_CHK_CFG,			0x2c),
> -	REG(DEV_MAC_IFG_CFG,				0x30),
> -	REG(DEV_MAC_HDX_CFG,				0x34),
> -	REG(DEV_MAC_DBG_CFG,				0x38),
> -	REG(DEV_MAC_FC_MAC_LOW_CFG,			0x3c),
> -	REG(DEV_MAC_FC_MAC_HIGH_CFG,			0x40),
> -	REG(DEV_MAC_STICKY,				0x44),
> -	REG(PCS1G_CFG,					0x48),
> -	REG(PCS1G_MODE_CFG,				0x4c),
> -	REG(PCS1G_SD_CFG,				0x50),
> -	REG(PCS1G_ANEG_CFG,				0x54),
> -	REG(PCS1G_ANEG_NP_CFG,				0x58),
> -	REG(PCS1G_LB_CFG,				0x5c),
> -	REG(PCS1G_DBG_CFG,				0x60),
> -	REG(PCS1G_CDET_CFG,				0x64),
> -	REG(PCS1G_ANEG_STATUS,				0x68),
> -	REG(PCS1G_ANEG_NP_STATUS,			0x6c),
> -	REG(PCS1G_LINK_STATUS,				0x70),
> -	REG(PCS1G_LINK_DOWN_CNT,			0x74),
> -	REG(PCS1G_STICKY,				0x78),
> -	REG(PCS1G_DEBUG_STATUS,				0x7c),
> -	REG(PCS1G_LPI_CFG,				0x80),
> -	REG(PCS1G_LPI_WAKE_ERROR_CNT,			0x84),
> -	REG(PCS1G_LPI_STATUS,				0x88),
> -	REG(PCS1G_TSTPAT_MODE_CFG,			0x8c),
> -	REG(PCS1G_TSTPAT_STATUS,			0x90),
> -	REG(DEV_PCS_FX100_CFG,				0x94),
> -	REG(DEV_PCS_FX100_STATUS,			0x98),
> -};
> -
>  static const u32 *ocelot_regmap[TARGET_MAX] = {
>  	[ANA] = ocelot_ana_regmap,
>  	[QS] = ocelot_qs_regmap,
> diff --git a/include/soc/mscc/ocelot_regs.h b/include/soc/mscc/ocelot_regs.h
> new file mode 100644
> index 000000000000..d4508eb9e04a
> --- /dev/null
> +++ b/include/soc/mscc/ocelot_regs.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
> +/*
> + * Microsemi Ocelot Switch driver
> + *
> + * Copyright (c) 2021 Innovative Advantage Inc.
> + */
> +
> +#ifndef OCELOT_REGS_H
> +#define OCELOT_REGS_H
> +
> +extern const u32 ocelot_ana_regmap[];
> +extern const u32 ocelot_qs_regmap[];
> +extern const u32 ocelot_qsys_regmap[];
> +extern const u32 ocelot_rew_regmap[];
> +extern const u32 ocelot_sys_regmap[];
> +extern const u32 ocelot_vcap_regmap[];
> +extern const u32 ocelot_ptp_regmap[];
> +extern const u32 ocelot_dev_gmii_regmap[];
> +
> +#endif
> -- 
> 2.25.1
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14 11:47   ` Vladimir Oltean
@ 2021-08-14 18:40     ` Colin Foster
  2021-08-14 19:08       ` Vladimir Oltean
  0 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-14 18:40 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 02:47:21PM +0300, Vladimir Oltean wrote:
> On Fri, Aug 13, 2021 at 07:50:03PM -0700, Colin Foster wrote:
> > +* phy_mode = "sgmii": on ports 0, 1, 2, 3
> 
> > +			port@0 {
> > +				reg = <0>;
> > +				ethernet = <&mac>;
> > +				phy-mode = "sgmii";
> > +
> > +				fixed-link {
> > +					speed = <100>;
> > +					full-duplex;
> > +				};
> > +			};
> 
> Your driver is unconditionally setting up the NPI port at gigabit and
> you claim it works, yet the device tree sees a 100Mbps fixed-link? Which
> one is right, what speed does the port operate at?

Good catch!

I made the change to ocelot_spi_vsc7512 yesterday to set it up as
gigabit, tested it, and it still works. Previously for my testing I'd
had it hard-coded to 100, because the Beaglebone I'm using only supports
100Mbps on eth0.

# phytool print swp1/0

ieee-phy: id:0x00070540

   ieee-phy: reg:BMCR(0x00) val:0x1040
      flags:          -reset -loopback ^[[1m+aneg-enable^[[0m -power-down -isolate -aneg-restart -collision-test
      speed:          1000-half

   ieee-phy: reg:BMSR(0x01) val:0x796d
      capabilities:   -100-b4 ^[[1m+100-f^[[0m ^[[1m+100-h^[[0m ^[[1m+10-f^[[0m ^[[1m+10-h^[[0m -100-t2-f -100-t2-h
      flags:          ^[[1m+ext-status^[[0m ^[[1m+aneg-complete^[[0m -remote-fault ^[[1m+aneg-capable^[[0m ^[[1m+link^[[0m -jabber ^[[1m+ext-register^[[0m


Of course I understand that "it works" is not the same as "it's correct"

What I wanted to accomplish was to use the speed parameter and set up
the link based on that. I looked through all the DSA drivers and
couldn't find anything that seems to do that. The closest thing I saw
was in mt7531_cpu_port_config where they set the speed to either 2500 or
1000 based on the interface. But nothing that I saw would explicitly set
the speed based on this parameter.

So I think there's something I'm missing. The fixed-link speed should apply to 
the CPU port on the switch (port@0)? Then eth0 can be manually set to a
specific speed, but if it doesn't match the fixed-link speed I'd be out
of luck? Or should an ip link or ethtool command to eth0 modify the
speeds of both sides of the connection? It feels like setting port@0 to
the fastest speed and letting it negotiate down to eth0 makes sense...

To ask the same question a different way:

I can currently run "ethtool -s eth0 speed 10 duplex full autoneg on" 
and the link at eth0 drops to 10Mbps. Pinging my desktop jumps from 
about 400us to about 600us when I do that.

Should I not be able to do that? It should be fixed at 100Mbps without
autoneg, end of story? Because in the current configuration it feels
like the fixed-link settings are more a suggestion than a rule...


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14 18:40     ` Colin Foster
@ 2021-08-14 19:08       ` Vladimir Oltean
  2021-08-14 23:41         ` Colin Foster
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-14 19:08 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 11:40:40AM -0700, Colin Foster wrote:
> On Sat, Aug 14, 2021 at 02:47:21PM +0300, Vladimir Oltean wrote:
> > On Fri, Aug 13, 2021 at 07:50:03PM -0700, Colin Foster wrote:
> > > +* phy_mode = "sgmii": on ports 0, 1, 2, 3
> > 
> > > +			port@0 {
> > > +				reg = <0>;
> > > +				ethernet = <&mac>;
> > > +				phy-mode = "sgmii";
> > > +
> > > +				fixed-link {
> > > +					speed = <100>;
> > > +					full-duplex;
> > > +				};
> > > +			};
> > 
> > Your driver is unconditionally setting up the NPI port at gigabit and
> > you claim it works, yet the device tree sees a 100Mbps fixed-link? Which
> > one is right, what speed does the port operate at?
> 
> Good catch!
> 
> I made the change to ocelot_spi_vsc7512 yesterday to set it up as
> gigabit, tested it, and it still works. Previously for my testing I'd
> had it hard-coded to 100, because the Beaglebone I'm using only supports
> 100Mbps on eth0.
> 
> # phytool print swp1/0

Why are you showing the PHY registers of swp1? Why are these relevant at all?

> 
> ieee-phy: id:0x00070540
> 
>    ieee-phy: reg:BMCR(0x00) val:0x1040
>       flags:          -reset -loopback ^[[1m+aneg-enable^[[0m -power-down -isolate -aneg-restart -collision-test
>       speed:          1000-half

Also, 1000/half sounds like an odd speed to end negotiation at.

> 
>    ieee-phy: reg:BMSR(0x01) val:0x796d
>       capabilities:   -100-b4 ^[[1m+100-f^[[0m ^[[1m+100-h^[[0m ^[[1m+10-f^[[0m ^[[1m+10-h^[[0m -100-t2-f -100-t2-h
>       flags:          ^[[1m+ext-status^[[0m ^[[1m+aneg-complete^[[0m -remote-fault ^[[1m+aneg-capable^[[0m ^[[1m+link^[[0m -jabber ^[[1m+ext-register^[[0m
> 
> 
> Of course I understand that "it works" is not the same as "it's correct"
> 
> What I wanted to accomplish was to use the speed parameter and set up
> the link based on that. I looked through all the DSA drivers and
> couldn't find anything that seems to do that. The closest thing I saw
> was in mt7531_cpu_port_config where they set the speed to either 2500 or
> 1000 based on the interface. But nothing that I saw would explicitly set
> the speed based on this parameter.

As I mentioned in the other email, .phylink_mac_link_up is the function
you are looking for. Phylink parses the fixed-link and calls that
function for fixed-link ports with the speed and duplex specified. Check
and see if felix_phylink_mac_link_up is not in fact called with
link_an_mode == MLO_AN_FIXED, speed == SPEED_100 and duplex == DUPLEX_FULL,
then what you are doing with that and if it makes sense for what you are
trying to do.

> 
> So I think there's something I'm missing. The fixed-link speed should apply to 
> the CPU port on the switch (port@0)?

Is this a question? It is under port@0, the port with the 'ethernet'
property i.e. the CPU port, so why should it not?

> Then eth0 can be manually set to a specific speed, but if it doesn't
> match the fixed-link speed I'd be out of luck? Or should an ip link or
> ethtool command to eth0 modify the speeds of both sides of the
> connection? It feels like setting port@0 to the fastest speed and
> letting it negotiate down to eth0 makes sense...
> 
> To ask the same question a different way:
> 
> I can currently run "ethtool -s eth0 speed 10 duplex full autoneg on" 
> and the link at eth0 drops to 10Mbps. Pinging my desktop jumps from 
> about 400us to about 600us when I do that.

If eth0 is also a fixed-link, you should not be able to do that, no.
But the fact that you are able to do that means it's not a fixed-link,
you have a pair of PHYs that freely auto-negotiate the speed between the
BeagleBone and the switch.

> 
> Should I not be able to do that? It should be fixed at 100Mbps without
> autoneg, end of story? Because in the current configuration it feels
> like the fixed-link settings are more a suggestion than a rule...
> 

It should describe the hardware configuration, of course. It is
incorrect to describe one side of a copper PHY connection as fixed-link
and the other as having a phy-handle, and it sounds like this is what
you're doing. We need to see the device tree binding for eth0, and
maybe a picture of your setup if that is possible. How do you connect
the switch board to the BeagleBone? Is it an RJ45 cable or some sort of
PCIe-style connector with fingers for an SGMII SERDES lane, in which the
board is plugged?

The device tree says SGMII, the behavior says RJ45.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14 19:08       ` Vladimir Oltean
@ 2021-08-14 23:41         ` Colin Foster
  2021-08-15  0:00           ` Vladimir Oltean
  0 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-14 23:41 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 10:08:54PM +0300, Vladimir Oltean wrote:
> On Sat, Aug 14, 2021 at 11:40:40AM -0700, Colin Foster wrote:
> > On Sat, Aug 14, 2021 at 02:47:21PM +0300, Vladimir Oltean wrote:
> > > On Fri, Aug 13, 2021 at 07:50:03PM -0700, Colin Foster wrote:
> > > > +* phy_mode = "sgmii": on ports 0, 1, 2, 3
> > > 
> > > > +			port@0 {
> > > > +				reg = <0>;
> > > > +				ethernet = <&mac>;
> > > > +				phy-mode = "sgmii";
> > > > +
> > > > +				fixed-link {
> > > > +					speed = <100>;
> > > > +					full-duplex;
> > > > +				};
> > > > +			};
> > > 
> > > Your driver is unconditionally setting up the NPI port at gigabit and
> > > you claim it works, yet the device tree sees a 100Mbps fixed-link? Which
> > > one is right, what speed does the port operate at?
> > 
> > Good catch!
> > 
> > I made the change to ocelot_spi_vsc7512 yesterday to set it up as
> > gigabit, tested it, and it still works. Previously for my testing I'd
> > had it hard-coded to 100, because the Beaglebone I'm using only supports
> > 100Mbps on eth0.
> > 
> > # phytool print swp1/0
> 
> Why are you showing the PHY registers of swp1? Why are these relevant at all?

Some sleight of hand. I'm not sure there's a different way to do it, but
running print on swp1/0 gives phy address 0 on the bus that contains
swp1. So in this setup, swp1/0 is the same as swp2/0, swp3/0 and swp4/0,
all of which point to the registers associated with "swp0" from what I
understand.

> 
> > 
> > ieee-phy: id:0x00070540
> > 
> >    ieee-phy: reg:BMCR(0x00) val:0x1040
> >       flags:          -reset -loopback ^[[1m+aneg-enable^[[0m -power-down -isolate -aneg-restart -collision-test
> >       speed:          1000-half
> 
> Also, 1000/half sounds like an odd speed to end negotiation at.

Agreed. Possibly a misunderstanding by me during
vsc7512_enable_npi_port? I'll look into this.

> 
> > 
> >    ieee-phy: reg:BMSR(0x01) val:0x796d
> >       capabilities:   -100-b4 ^[[1m+100-f^[[0m ^[[1m+100-h^[[0m ^[[1m+10-f^[[0m ^[[1m+10-h^[[0m -100-t2-f -100-t2-h
> >       flags:          ^[[1m+ext-status^[[0m ^[[1m+aneg-complete^[[0m -remote-fault ^[[1m+aneg-capable^[[0m ^[[1m+link^[[0m -jabber ^[[1m+ext-register^[[0m
> > 
> > 
> > Of course I understand that "it works" is not the same as "it's correct"
> > 
> > What I wanted to accomplish was to use the speed parameter and set up
> > the link based on that. I looked through all the DSA drivers and
> > couldn't find anything that seems to do that. The closest thing I saw
> > was in mt7531_cpu_port_config where they set the speed to either 2500 or
> > 1000 based on the interface. But nothing that I saw would explicitly set
> > the speed based on this parameter.
> 
> As I mentioned in the other email, .phylink_mac_link_up is the function
> you are looking for. Phylink parses the fixed-link and calls that
> function for fixed-link ports with the speed and duplex specified. Check
> and see if felix_phylink_mac_link_up is not in fact called with
> link_an_mode == MLO_AN_FIXED, speed == SPEED_100 and duplex == DUPLEX_FULL,
> then what you are doing with that and if it makes sense for what you are
> trying to do.

I'll reply there once I've absorbed everything.

> 
> > 
> > So I think there's something I'm missing. The fixed-link speed should apply to 
> > the CPU port on the switch (port@0)?
> 
> Is this a question? It is under port@0, the port with the 'ethernet'
> property i.e. the CPU port, so why should it not?
> 
> > Then eth0 can be manually set to a specific speed, but if it doesn't
> > match the fixed-link speed I'd be out of luck? Or should an ip link or
> > ethtool command to eth0 modify the speeds of both sides of the
> > connection? It feels like setting port@0 to the fastest speed and
> > letting it negotiate down to eth0 makes sense...
> > 
> > To ask the same question a different way:
> > 
> > I can currently run "ethtool -s eth0 speed 10 duplex full autoneg on" 
> > and the link at eth0 drops to 10Mbps. Pinging my desktop jumps from 
> > about 400us to about 600us when I do that.
> 
> If eth0 is also a fixed-link, you should not be able to do that, no.
> But the fact that you are able to do that means it's not a fixed-link,
> you have a pair of PHYs that freely auto-negotiate the speed between the
> BeagleBone and the switch.

Yes, that is my setup. Addressed below.

> 
> > 
> > Should I not be able to do that? It should be fixed at 100Mbps without
> > autoneg, end of story? Because in the current configuration it feels
> > like the fixed-link settings are more a suggestion than a rule...
> > 
> 
> It should describe the hardware configuration, of course. It is
> incorrect to describe one side of a copper PHY connection as fixed-link
> and the other as having a phy-handle, and it sounds like this is what
> you're doing. We need to see the device tree binding for eth0, and
> maybe a picture of your setup if that is possible. How do you connect
> the switch board to the BeagleBone? Is it an RJ45 cable or some sort of
> PCIe-style connector with fingers for an SGMII SERDES lane, in which the
> board is plugged?
> 
> The device tree says SGMII, the behavior says RJ45.

I'm using the standard BeagleBone devicetree, so &mac is defined in
arch/arm/boot/dts/am335x-bone-common.dtsi. For this stage of development
I'm using an ethernet cable plugged from the BeagleBone to port 0 of the
VSC7512 dev board. I haven't done anything more to the
am335x-boneblack.dts other than add the spi and switch configurations.
The connections between the beaglebone and dev board are limited to the
4 SPI lines, a ground, and an ethernet cable.

So DSA requires a fixed-link property. And that makes sense... who in
their right mind would connect switches on a board using an RJ45
connection :) Then the only reason any of this is working is because I
have eth0 set up as an RJ45 connection, and because of that I need the
hack to enable the phy on the switch port 0...

Maybe that's a question:
Is my devicetree incorrect for claiming the connection is SGMII when it
should be RJ45? Or is my setup incorrect for using RJ45 and there's no
way to configure it that way, so the fact that it functions is an
anomaly?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14 23:41         ` Colin Foster
@ 2021-08-15  0:00           ` Vladimir Oltean
  2021-08-15  1:08             ` Colin Foster
  0 siblings, 1 reply; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-15  0:00 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 04:41:58PM -0700, Colin Foster wrote:
> So DSA requires a fixed-link property.

How did you come to that conclusion? As mentioned twice already, DSA
registers a phylink for the CPU port, and phylink works with either a
phy-handle or a fixed-link.

Support for this has been added more than 2 years ago:
https://patchwork.ozlabs.org/project/netdev/patch/1558992127-26008-11-git-send-email-ioana.ciornei@nxp.com/

You have a PHY... so use a phy-handle.

> And that makes sense... who in
> their right mind would connect switches on a board using an RJ45
> connection :) Then the only reason any of this is working is because I
> have eth0 set up as an RJ45 connection, and because of that I need the
> hack to enable the phy on the switch port 0...
> 
> Maybe that's a question:
> Is my devicetree incorrect for claiming the connection is SGMII when it
> should be RJ45?

Your device tree description is absolutely incorrect by all accounts.

First of all, "is SGMII" does not really preclude "is RJ45", because you
can have an external PHY connected to your MAC via SGMII, and that
external PHY would provide RJ45 access. That would be absolutely fine too.

That would be described as:

	port@0 {
		phy-mode = "sgmii";
		phy-handle = <&external_phy>;
	};

It would be absolutely fine as well to describe the RJ45 port via an
internal PHY if that's how things are hooked up in your eval board
(really don't know what PHY you have, sorry):

	port@0 {
		phy-mode = "internal";
		phy-handle = <&internal_phy>;
	};

But in the absence of a phy-handle and the presence of fixed-link, like
the way you are describing it, you are telling Linux that you have an
SGMII PHY-less system, where the SGMII lane goes directly towards the
outside world.

I think it is actually written somewhere in the documentation that
describing a connection to a PHY using a fixed-link is wrong and
strongly discouraged.

> Or is my setup incorrect for using RJ45 and there's no
> way to configure it that way, so the fact that it functions is an
> anomaly?

No, the setup is not incorrect, it is just fine and both DSA and phylink
support it as long as it is described properly, with the adequate
phy-handle on the CPU port.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-15  0:00           ` Vladimir Oltean
@ 2021-08-15  1:08             ` Colin Foster
  0 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-15  1:08 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sun, Aug 15, 2021 at 03:00:41AM +0300, Vladimir Oltean wrote:
> On Sat, Aug 14, 2021 at 04:41:58PM -0700, Colin Foster wrote:
> > So DSA requires a fixed-link property.
> 
> How did you come to that conclusion? As mentioned twice already, DSA
> registers a phylink for the CPU port, and phylink works with either a
> phy-handle or a fixed-link.
> 
> Support for this has been added more than 2 years ago:
> https://patchwork.ozlabs.org/project/netdev/patch/1558992127-26008-11-git-send-email-ioana.ciornei@nxp.com/
> 
> You have a PHY... so use a phy-handle.

My misunderstanding. I think I saw all the documentation / examples and
understood that to be "it must be this way". I shouldn't have drawn that
conclusion.

> 
> > And that makes sense... who in
> > their right mind would connect switches on a board using an RJ45
> > connection :) Then the only reason any of this is working is because I
> > have eth0 set up as an RJ45 connection, and because of that I need the
> > hack to enable the phy on the switch port 0...
> > 
> > Maybe that's a question:
> > Is my devicetree incorrect for claiming the connection is SGMII when it
> > should be RJ45?
> 
> Your device tree description is absolutely incorrect by all accounts.
> 
> First of all, "is SGMII" does not really preclude "is RJ45", because you
> can have an external PHY connected to your MAC via SGMII, and that
> external PHY would provide RJ45 access. That would be absolutely fine too.
> 
> That would be described as:
> 
> 	port@0 {
> 		phy-mode = "sgmii";
> 		phy-handle = <&external_phy>;
> 	};
> 
> It would be absolutely fine as well to describe the RJ45 port via an
> internal PHY if that's how things are hooked up in your eval board
> (really don't know what PHY you have, sorry):
> 
> 	port@0 {
> 		phy-mode = "internal";
> 		phy-handle = <&internal_phy>;
> 	};
> 
> But in the absence of a phy-handle and the presence of fixed-link, like
> the way you are describing it, you are telling Linux that you have an
> SGMII PHY-less system, where the SGMII lane goes directly towards the
> outside world.
> 

Understood, and thank you for the feedback. I am definitely not
currently running in a PHY-less system on this interface. I also had
some confusion about phy-mode = "internal" vs phy-mode = "sgmii". It
seems like I have ports 1-3 incorrectly confiugred as well - they are
internal to the VSC7512 chip.

> I think it is actually written somewhere in the documentation that
> describing a connection to a PHY using a fixed-link is wrong and
> strongly discouraged.

I have some reading to do. I made assumptions early on and now that
things seem to be getting close, it is becoming clear that those
misunderstandings were leading me down the wrong path.

> 
> > Or is my setup incorrect for using RJ45 and there's no
> > way to configure it that way, so the fact that it functions is an
> > anomaly?
> 
> No, the setup is not incorrect, it is just fine and both DSA and phylink
> support it as long as it is described properly, with the adequate
> phy-handle on the CPU port.

This is very good to know. Thank you. I'm sorry that you're having to
troubleshoot my devicetree, but it is incerdibly helpful to just know
"the devicetree is wrong" instead of "my implementation of the driver
has this shortcoming." I have another round of dev / testing ahead of
me.

Again, a sincere thank you for the feedback. I understand I'm making a
lot of mistakes. I'm hopeful that these mistakes can come off as
"inexperienced" and, frankly, that I'm not annoying everyone.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-14 12:02     ` Vladimir Oltean
@ 2021-08-15 19:10       ` Colin Foster
  2021-08-15 20:41       ` Colin Foster
  2021-08-15 21:35       ` Russell King (Oracle)
  2 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-15 19:10 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 03:02:11PM +0300, Vladimir Oltean wrote:
> On Sat, Aug 14, 2021 at 02:43:29PM +0300, Vladimir Oltean wrote:
> > The issue is that the registers for the PCS1G block look nothing like
> > the MDIO clause 22 layout, so anything that tries to map the struct
> > ocelot_pcs over a struct mdio_device is going to look like a horrible
> > shoehorn.
> > 
> > For that we might need Russell's assistance.
> > 
> > The documentation is at:
> > http://ww1.microchip.com/downloads/en/DeviceDoc/VMDS-10489.pdf
> > search for "Information about the registers for this product is available in the attached file."
> > and then open the PDF embedded within the PDF.
> 
> In fact I do notice now that as long as you don't use any of the
> optional phylink_mii_c22_pcs_* helpers in your PCS driver, then
> struct phylink_pcs has pretty much zero dependency on struct mdio_device,
> which means that I'm wrong and it should be completely within reach to
> write a dedicated PCS driver for this hardware.
> 
> As to how to make the common felix.c work with different implementations
> of struct phylink_pcs, one thing that certainly has to change is that
> struct felix should hold a struct phylink_pcs **pcs and not a
> struct lynx_pcs **pcs.
> 
> Does this mean that we should refactor lynx_pcs_create() to return a
> struct phylink_pcs * instead of struct lynx_pcs *, and lynx_pcs_destroy()
> to receive the struct phylink_pcs *, use container_of() and free the
> larger struct lynx_pcs *? Yes, probably.
> 
> If you feel uncomfortable with this, I can try to refactor lynx_pcs to
> make it easier to accomodate a different PCS driver in felix.

I think this is pretty straightforward. That seems like the same thing
I'd done to get regmap working in this patch since my first attempt.

Should this be a new commit in this patchset or a standalone patch?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-14 12:02     ` Vladimir Oltean
  2021-08-15 19:10       ` Colin Foster
@ 2021-08-15 20:41       ` Colin Foster
  2021-08-15 23:14         ` Russell King (Oracle)
  2021-08-17  9:41         ` Vladimir Oltean
  2021-08-15 21:35       ` Russell King (Oracle)
  2 siblings, 2 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-15 20:41 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 03:02:11PM +0300, Vladimir Oltean wrote:
> On Sat, Aug 14, 2021 at 02:43:29PM +0300, Vladimir Oltean wrote:
> > The issue is that the registers for the PCS1G block look nothing like
> > the MDIO clause 22 layout, so anything that tries to map the struct
> > ocelot_pcs over a struct mdio_device is going to look like a horrible
> > shoehorn.
> > 
> > For that we might need Russell's assistance.
> > 
> > The documentation is at:
> > http://ww1.microchip.com/downloads/en/DeviceDoc/VMDS-10489.pdf
> > search for "Information about the registers for this product is available in the attached file."
> > and then open the PDF embedded within the PDF.
> 
> In fact I do notice now that as long as you don't use any of the
> optional phylink_mii_c22_pcs_* helpers in your PCS driver, then
> struct phylink_pcs has pretty much zero dependency on struct mdio_device,
> which means that I'm wrong and it should be completely within reach to
> write a dedicated PCS driver for this hardware.
> 
> As to how to make the common felix.c work with different implementations
> of struct phylink_pcs, one thing that certainly has to change is that
> struct felix should hold a struct phylink_pcs **pcs and not a
> struct lynx_pcs **pcs.
> 
> Does this mean that we should refactor lynx_pcs_create() to return a
> struct phylink_pcs * instead of struct lynx_pcs *, and lynx_pcs_destroy()
> to receive the struct phylink_pcs *, use container_of() and free the
> larger struct lynx_pcs *? Yes, probably.
> 
> If you feel uncomfortable with this, I can try to refactor lynx_pcs to
> make it easier to accomodate a different PCS driver in felix.

I believe I'll need to rebase this commit before I send it out to the
maintainers, but is this what you had in mind?

I also came across some curious code in Seville where it is callocing a
struct phy_device * array instead of struct lynx_pcs *. I'm not sure if
that's technically a bug or if the thought is "a pointer array is a 
pointer array."

From 323d2f68447c3532dba0d85c636ea14c66aa098f Mon Sep 17 00:00:00 2001
From: Colin Foster <colin.foster@in-advantage.com>
Date: Sun, 15 Aug 2021 13:07:47 -0700
Subject: [RFC PATCH v3 net-next] net: phy: lynx: refactor Lynx PCS module to
 use generic phylink_pcs

Remove references to lynx_pcs structures so drivers like the Felix DSA
can reference alternate PCS drivers.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
---
 drivers/net/dsa/ocelot/felix.h                |  2 +-
 drivers/net/dsa/ocelot/felix_vsc9959.c        | 10 ++++-----
 drivers/net/dsa/ocelot/seville_vsc9953.c      | 12 +++++-----
 .../net/ethernet/freescale/dpaa2/dpaa2-mac.c  |  7 +++---
 .../net/ethernet/freescale/dpaa2/dpaa2-mac.h  |  3 +--
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 12 +++++-----
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  4 ++--
 drivers/net/pcs/pcs-lynx.c                    | 22 +++++++++++++++----
 include/linux/pcs-lynx.h                      |  9 +++-----
 9 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index c872705115bc..f51e9e8064fc 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -58,7 +58,7 @@ struct felix {
 	const struct felix_info		*info;
 	struct ocelot			ocelot;
 	struct mii_bus			*imdio;
-	struct lynx_pcs			**pcs;
+	struct phylink_pcs		**pcs;
 	resource_size_t			switch_base;
 	resource_size_t			imdio_base;
 	struct dsa_8021q_context	*dsa_8021q_ctx;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index a84129d18007..d0b3f6be360f 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1046,7 +1046,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
 	int rc;
 
 	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
-				  sizeof(struct lynx_pcs *),
+				  sizeof(struct phylink_pcs *),
 				  GFP_KERNEL);
 	if (!felix->pcs) {
 		dev_err(dev, "failed to allocate array for PCS PHYs\n");
@@ -1095,8 +1095,8 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
 
 	for (port = 0; port < felix->info->num_ports; port++) {
 		struct ocelot_port *ocelot_port = ocelot->ports[port];
+		struct phylink_pcs *phylink;
 		struct mdio_device *pcs;
-		struct lynx_pcs *lynx;
 
 		if (dsa_is_unused_port(felix->ds, port))
 			continue;
@@ -1108,13 +1108,13 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
 		if (IS_ERR(pcs))
 			continue;
 
-		lynx = lynx_pcs_create(pcs);
+		phylink = lynx_pcs_create(pcs);
 		if (!lynx) {
 			mdio_device_free(pcs);
 			continue;
 		}
 
-		felix->pcs[port] = lynx;
+		felix->pcs[port] = phylink;
 
 		dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
 	}
@@ -1128,7 +1128,7 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
 	int port;
 
 	for (port = 0; port < ocelot->num_phys_ports; port++) {
-		struct lynx_pcs *pcs = felix->pcs[port];
+		struct phylink_pcs *pcs = felix->pcs[port];
 
 		if (!pcs)
 			continue;
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 540cf5bc9c54..8200cc5dd24d 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -1007,7 +1007,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
 	int rc;
 
 	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
-				  sizeof(struct phy_device *),
+				  sizeof(struct phylink_pcs *),
 				  GFP_KERNEL);
 	if (!felix->pcs) {
 		dev_err(dev, "failed to allocate array for PCS PHYs\n");
@@ -1029,8 +1029,8 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
 	for (port = 0; port < felix->info->num_ports; port++) {
 		struct ocelot_port *ocelot_port = ocelot->ports[port];
 		int addr = port + 4;
+		struct phylink_pcs *phylink;
 		struct mdio_device *pcs;
-		struct lynx_pcs *lynx;
 
 		if (dsa_is_unused_port(felix->ds, port))
 			continue;
@@ -1042,13 +1042,13 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
 		if (IS_ERR(pcs))
 			continue;
 
-		lynx = lynx_pcs_create(pcs);
+		phylink = lynx_pcs_create(pcs);
 		if (!lynx) {
 			mdio_device_free(pcs);
 			continue;
 		}
 
-		felix->pcs[port] = lynx;
+		felix->pcs[port] = phylink;
 
 		dev_info(dev, "Found PCS at internal MDIO address %d\n", addr);
 	}
@@ -1062,12 +1062,12 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
 	int port;
 
 	for (port = 0; port < ocelot->num_phys_ports; port++) {
-		struct lynx_pcs *pcs = felix->pcs[port];
+		struct phylink_pcs *pcs = felix->pcs[port];
 
 		if (!pcs)
 			continue;
 
-		mdio_device_free(pcs->mdio);
+		mdio_device_free(lynx_pcs_get_mdio(pcs));
 		lynx_pcs_destroy(pcs);
 	}
 	felix_mdio_bus_free(ocelot);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index ccaf7e35abeb..484f0d4efefe 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -270,10 +270,11 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
 
 static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
 {
-	struct lynx_pcs *pcs = mac->pcs;
+	struct phylink_pcs *pcs = mac->pcs;
 
 	if (pcs) {
-		struct device *dev = &pcs->mdio->dev;
+		struct mdio_device *mdio = lynx_get_mdio_device(pcs);
+		struct device *dev = &mdio->dev;
 		lynx_pcs_destroy(pcs);
 		put_device(dev);
 		mac->pcs = NULL;
@@ -336,7 +337,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
 	mac->phylink = phylink;
 
 	if (mac->pcs)
-		phylink_set_pcs(mac->phylink, &mac->pcs->pcs);
+		phylink_set_pcs(mac->phylink, mac->pcs);
 
 	err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
 	if (err) {
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
index 13d42dd58ec9..d1d22b52a960 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
@@ -7,7 +7,6 @@
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/phylink.h>
-#include <linux/pcs-lynx.h>
 
 #include "dpmac.h"
 #include "dpmac-cmd.h"
@@ -23,7 +22,7 @@ struct dpaa2_mac {
 	struct phylink *phylink;
 	phy_interface_t if_mode;
 	enum dpmac_link_type if_link_type;
-	struct lynx_pcs *pcs;
+	struct phylink_pcs *pcs;
 };
 
 bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 31274325159a..cc2ca51ac984 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -823,7 +823,7 @@ static int enetc_imdio_create(struct enetc_pf *pf)
 {
 	struct device *dev = &pf->si->pdev->dev;
 	struct enetc_mdio_priv *mdio_priv;
-	struct lynx_pcs *pcs_lynx;
+	struct phylink_pcs *pcs_phylink;
 	struct mdio_device *pcs;
 	struct mii_bus *bus;
 	int err;
@@ -855,8 +855,8 @@ static int enetc_imdio_create(struct enetc_pf *pf)
 		goto unregister_mdiobus;
 	}
 
-	pcs_lynx = lynx_pcs_create(pcs);
-	if (!pcs_lynx) {
+	pcs_phylink = lynx_pcs_create(pcs);
+	if (!pcs_phylink) {
 		mdio_device_free(pcs);
 		err = -ENOMEM;
 		dev_err(dev, "cannot create lynx pcs (%d)\n", err);
@@ -864,7 +864,7 @@ static int enetc_imdio_create(struct enetc_pf *pf)
 	}
 
 	pf->imdio = bus;
-	pf->pcs = pcs_lynx;
+	pf->pcs = pcs_phylink;
 
 	return 0;
 
@@ -878,7 +878,7 @@ static int enetc_imdio_create(struct enetc_pf *pf)
 static void enetc_imdio_remove(struct enetc_pf *pf)
 {
 	if (pf->pcs) {
-		mdio_device_free(pf->pcs->mdio);
+		mdio_device_free(lynx_get_mdio_device(pf->pcs));
 		lynx_pcs_destroy(pf->pcs);
 	}
 	if (pf->imdio) {
@@ -977,7 +977,7 @@ static void enetc_pl_mac_config(struct phylink_config *config,
 
 	priv = netdev_priv(pf->si->ndev);
 	if (pf->pcs)
-		phylink_set_pcs(priv->phylink, &pf->pcs->pcs);
+		phylink_set_pcs(priv->phylink, &pf->pcs);
 }
 
 static void enetc_force_rgmii_mac(struct enetc_hw *hw, int speed, int duplex)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 263946c51e37..c26bd66e4597 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -2,7 +2,7 @@
 /* Copyright 2017-2019 NXP */
 
 #include "enetc.h"
-#include <linux/pcs-lynx.h>
+#include <linux/phylink.h>
 
 #define ENETC_PF_NUM_RINGS	8
 
@@ -46,7 +46,7 @@ struct enetc_pf {
 
 	struct mii_bus *mdio; /* saved for cleanup */
 	struct mii_bus *imdio;
-	struct lynx_pcs *pcs;
+	struct phylink_pcs *pcs;
 
 	phy_interface_t if_mode;
 	struct phylink_config phylink_config;
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index af36cd647bf5..bdefcb36e913 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -22,6 +22,11 @@
 #define IF_MODE_SPEED_MSK		GENMASK(3, 2)
 #define IF_MODE_HALF_DUPLEX		BIT(4)
 
+struct lynx_pcs {
+	struct phylink_pcs pcs;
+	struct mdio_device *mdio;
+};
+
 enum sgmii_speed {
 	SGMII_SPEED_10		= 0,
 	SGMII_SPEED_100		= 1,
@@ -30,6 +35,15 @@ enum sgmii_speed {
 };
 
 #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
+#define lynx_to_phylink_pcs(lynx) (&lynx->pcs)
+
+struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs)
+{
+	struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
+
+	return lynx->mdio;
+}
+EXPORT_SYMBOL(lynx_get_mdio_device);
 
 static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
 				       struct phylink_link_state *state)
@@ -329,7 +343,7 @@ static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
 	.pcs_link_up = lynx_pcs_link_up,
 };
 
-struct lynx_pcs *lynx_pcs_create(struct mdio_device *mdio)
+struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
 {
 	struct lynx_pcs *lynx_pcs;
 
@@ -341,13 +355,13 @@ struct lynx_pcs *lynx_pcs_create(struct mdio_device *mdio)
 	lynx_pcs->pcs.ops = &lynx_pcs_phylink_ops;
 	lynx_pcs->pcs.poll = true;
 
-	return lynx_pcs;
+	return lynx_to_phylink_pcs(lynx_pcs);
 }
 EXPORT_SYMBOL(lynx_pcs_create);
 
-void lynx_pcs_destroy(struct lynx_pcs *pcs)
+void lynx_pcs_destroy(struct phylink_pcs *pcs)
 {
-	kfree(pcs);
+	kfree(phylink_pcs_to_lynx(pcs));
 }
 EXPORT_SYMBOL(lynx_pcs_destroy);
 
diff --git a/include/linux/pcs-lynx.h b/include/linux/pcs-lynx.h
index a6440d6ebe95..5712cc2ce775 100644
--- a/include/linux/pcs-lynx.h
+++ b/include/linux/pcs-lynx.h
@@ -9,13 +9,10 @@
 #include <linux/mdio.h>
 #include <linux/phylink.h>
 
-struct lynx_pcs {
-	struct phylink_pcs pcs;
-	struct mdio_device *mdio;
-};
+struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs);
 
-struct lynx_pcs *lynx_pcs_create(struct mdio_device *mdio);
+struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio);
 
-void lynx_pcs_destroy(struct lynx_pcs *pcs);
+void lynx_pcs_destroy(struct phylink_pcs *pcs);
 
 #endif /* __LINUX_PCS_LYNX_H */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-14 12:02     ` Vladimir Oltean
  2021-08-15 19:10       ` Colin Foster
  2021-08-15 20:41       ` Colin Foster
@ 2021-08-15 21:35       ` Russell King (Oracle)
  2 siblings, 0 replies; 36+ messages in thread
From: Russell King (Oracle) @ 2021-08-15 21:35 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Colin Foster, andrew, vivien.didelot, f.fainelli, davem, kuba,
	robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 03:02:11PM +0300, Vladimir Oltean wrote:
> In fact I do notice now that as long as you don't use any of the
> optional phylink_mii_c22_pcs_* helpers in your PCS driver, then
> struct phylink_pcs has pretty much zero dependency on struct mdio_device,
> which means that I'm wrong and it should be completely within reach to
> write a dedicated PCS driver for this hardware.

Yes, this was one of the design goals when I created phylink_pcs, as I
have exactly this situation with my hardware - PCS that do not have a
MDIO interface and do not conform to MDIO register layouts. So, I
explicitly ensured that phylink_pcs, just like the rest of phylink,
is not tied to any particular model of how hardware should look like.

Glad to see that this design decision is coming in handy for other
people now. :)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-15 20:41       ` Colin Foster
@ 2021-08-15 23:14         ` Russell King (Oracle)
  2021-08-15 23:27           ` Colin Foster
  2021-08-17  9:41         ` Vladimir Oltean
  1 sibling, 1 reply; 36+ messages in thread
From: Russell King (Oracle) @ 2021-08-15 23:14 UTC (permalink / raw)
  To: Colin Foster
  Cc: Vladimir Oltean, andrew, vivien.didelot, f.fainelli, davem, kuba,
	robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, netdev, devicetree, linux-kernel

On Sun, Aug 15, 2021 at 01:41:49PM -0700, Colin Foster wrote:
> I also came across some curious code in Seville where it is callocing a
> struct phy_device * array instead of struct lynx_pcs *. I'm not sure if
> that's technically a bug or if the thought is "a pointer array is a 
> pointer array."

I won't comment on that, but a few things I spotted in the patch:

> diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
> index a84129d18007..d0b3f6be360f 100644
> --- a/drivers/net/dsa/ocelot/felix_vsc9959.c
> +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
> @@ -1046,7 +1046,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
>  	int rc;
>  
>  	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
> -				  sizeof(struct lynx_pcs *),
> +				  sizeof(struct phylink_pcs *),
>  				  GFP_KERNEL);
>  	if (!felix->pcs) {
>  		dev_err(dev, "failed to allocate array for PCS PHYs\n");
> @@ -1095,8 +1095,8 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
>  
>  	for (port = 0; port < felix->info->num_ports; port++) {
>  		struct ocelot_port *ocelot_port = ocelot->ports[port];
> +		struct phylink_pcs *phylink;
>  		struct mdio_device *pcs;
> -		struct lynx_pcs *lynx;

Normally, "phylink" is used to refer to the main phylink data
structure, so I'm not too thrilled to see it getting re-used for the
PCS. However, as you have a variable called "pcs" already, I suppose
you don't have much choice.

That said, it would be nice to have consistent naming through at
least a single file, and you do have "pcs" below to refer to this
same thing.

Maybe using plpcs or ppcs would suffice? Or maybe use the "long name"
of phylink_pcs ?

>  
>  		if (dsa_is_unused_port(felix->ds, port))
>  			continue;
> @@ -1108,13 +1108,13 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
>  		if (IS_ERR(pcs))
>  			continue;
>  
> -		lynx = lynx_pcs_create(pcs);
> +		phylink = lynx_pcs_create(pcs);
>  		if (!lynx) {

I think you want to change this test.

>  			mdio_device_free(pcs);
>  			continue;
>  		}
>  
> -		felix->pcs[port] = lynx;
> +		felix->pcs[port] = phylink;
>  
>  		dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
>  	}
> @@ -1128,7 +1128,7 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
>  	int port;
>  
>  	for (port = 0; port < ocelot->num_phys_ports; port++) {
> -		struct lynx_pcs *pcs = felix->pcs[port];
> +		struct phylink_pcs *pcs = felix->pcs[port];
>  
>  		if (!pcs)
>  			continue;
> diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
> index 540cf5bc9c54..8200cc5dd24d 100644
> --- a/drivers/net/dsa/ocelot/seville_vsc9953.c
> +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
> @@ -1007,7 +1007,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
>  	int rc;
>  
>  	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
> -				  sizeof(struct phy_device *),
> +				  sizeof(struct phylink_pcs *),
>  				  GFP_KERNEL);
>  	if (!felix->pcs) {
>  		dev_err(dev, "failed to allocate array for PCS PHYs\n");
> @@ -1029,8 +1029,8 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
>  	for (port = 0; port < felix->info->num_ports; port++) {
>  		struct ocelot_port *ocelot_port = ocelot->ports[port];
>  		int addr = port + 4;
> +		struct phylink_pcs *phylink;
>  		struct mdio_device *pcs;
> -		struct lynx_pcs *lynx;
>  
>  		if (dsa_is_unused_port(felix->ds, port))
>  			continue;
> @@ -1042,13 +1042,13 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
>  		if (IS_ERR(pcs))
>  			continue;
>  
> -		lynx = lynx_pcs_create(pcs);
> +		phylink = lynx_pcs_create(pcs);
>  		if (!lynx) {

Same here.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-15 23:14         ` Russell King (Oracle)
@ 2021-08-15 23:27           ` Colin Foster
  2021-08-16  0:05             ` Russell King (Oracle)
  0 siblings, 1 reply; 36+ messages in thread
From: Colin Foster @ 2021-08-15 23:27 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Vladimir Oltean, andrew, vivien.didelot, f.fainelli, davem, kuba,
	robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, netdev, devicetree, linux-kernel

On Mon, Aug 16, 2021 at 12:14:54AM +0100, Russell King (Oracle) wrote:
> > diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
> > index a84129d18007..d0b3f6be360f 100644
> > --- a/drivers/net/dsa/ocelot/felix_vsc9959.c
> > +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
> > @@ -1046,7 +1046,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
> >  	int rc;
> >  
> >  	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
> > -				  sizeof(struct lynx_pcs *),
> > +				  sizeof(struct phylink_pcs *),
> >  				  GFP_KERNEL);
> >  	if (!felix->pcs) {
> >  		dev_err(dev, "failed to allocate array for PCS PHYs\n");
> > @@ -1095,8 +1095,8 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
> >  
> >  	for (port = 0; port < felix->info->num_ports; port++) {
> >  		struct ocelot_port *ocelot_port = ocelot->ports[port];
> > +		struct phylink_pcs *phylink;
> >  		struct mdio_device *pcs;
> > -		struct lynx_pcs *lynx;
> 
> Normally, "phylink" is used to refer to the main phylink data
> structure, so I'm not too thrilled to see it getting re-used for the
> PCS. However, as you have a variable called "pcs" already, I suppose
> you don't have much choice.
> 
> That said, it would be nice to have consistent naming through at
> least a single file, and you do have "pcs" below to refer to this
> same thing.
> 
> Maybe using plpcs or ppcs would suffice? Or maybe use the "long name"
> of phylink_pcs ?

I noticed this as well. It seems to me like the mdio_device variable
name of pcs is misleading, and perhaps should be "mdio" and phylink_pcs
should be pcs, or any of the alternatives you suggested.

> 
> >  
> >  		if (dsa_is_unused_port(felix->ds, port))
> >  			continue;
> > @@ -1108,13 +1108,13 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
> >  		if (IS_ERR(pcs))
> >  			continue;
> >  
> > -		lynx = lynx_pcs_create(pcs);
> > +		phylink = lynx_pcs_create(pcs);
> >  		if (!lynx) {
> 
> I think you want to change this test.

Yes, I caught these shortly after submitting it. Fixed.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-15 23:27           ` Colin Foster
@ 2021-08-16  0:05             ` Russell King (Oracle)
  0 siblings, 0 replies; 36+ messages in thread
From: Russell King (Oracle) @ 2021-08-16  0:05 UTC (permalink / raw)
  To: Colin Foster
  Cc: Vladimir Oltean, andrew, vivien.didelot, f.fainelli, davem, kuba,
	robh+dt, claudiu.manoil, alexandre.belloni, UNGLinuxDriver,
	hkallweit1, netdev, devicetree, linux-kernel

On Sun, Aug 15, 2021 at 04:27:53PM -0700, Colin Foster wrote:
> On Mon, Aug 16, 2021 at 12:14:54AM +0100, Russell King (Oracle) wrote:
> > > diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
> > > index a84129d18007..d0b3f6be360f 100644
> > > --- a/drivers/net/dsa/ocelot/felix_vsc9959.c
> > > +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
> > > @@ -1046,7 +1046,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
> > >  	int rc;
> > >  
> > >  	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
> > > -				  sizeof(struct lynx_pcs *),
> > > +				  sizeof(struct phylink_pcs *),
> > >  				  GFP_KERNEL);
> > >  	if (!felix->pcs) {
> > >  		dev_err(dev, "failed to allocate array for PCS PHYs\n");
> > > @@ -1095,8 +1095,8 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
> > >  
> > >  	for (port = 0; port < felix->info->num_ports; port++) {
> > >  		struct ocelot_port *ocelot_port = ocelot->ports[port];
> > > +		struct phylink_pcs *phylink;
> > >  		struct mdio_device *pcs;
> > > -		struct lynx_pcs *lynx;
> > 
> > Normally, "phylink" is used to refer to the main phylink data
> > structure, so I'm not too thrilled to see it getting re-used for the
> > PCS. However, as you have a variable called "pcs" already, I suppose
> > you don't have much choice.
> > 
> > That said, it would be nice to have consistent naming through at
> > least a single file, and you do have "pcs" below to refer to this
> > same thing.
> > 
> > Maybe using plpcs or ppcs would suffice? Or maybe use the "long name"
> > of phylink_pcs ?
> 
> I noticed this as well. It seems to me like the mdio_device variable
> name of pcs is misleading, and perhaps should be "mdio" and phylink_pcs
> should be pcs, or any of the alternatives you suggested.

Yes, we could alternatively could use mdiodev for mdio devices,
which would free up "pcs" for use with struct phylink_pcs.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
  2021-08-15 20:41       ` Colin Foster
  2021-08-15 23:14         ` Russell King (Oracle)
@ 2021-08-17  9:41         ` Vladimir Oltean
  1 sibling, 0 replies; 36+ messages in thread
From: Vladimir Oltean @ 2021-08-17  9:41 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel, Ioana Ciornei

On Sun, Aug 15, 2021 at 01:41:49PM -0700, Colin Foster wrote:
> I also came across some curious code in Seville where it is callocing a
> struct phy_device * array instead of struct lynx_pcs *. I'm not sure if
> that's technically a bug or if the thought is "a pointer array is a
> pointer array."

git blame will show you that it is a harmless leftover of commit
588d05504d2d ("net: dsa: ocelot: use the Lynx PCS helpers in Felix and
Seville"). Before that patch, the pcs was a struct phy_device.

> @@ -1062,12 +1062,12 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
>  	int port;
>
>  	for (port = 0; port < ocelot->num_phys_ports; port++) {
> -		struct lynx_pcs *pcs = felix->pcs[port];
> +		struct phylink_pcs *pcs = felix->pcs[port];
>
>  		if (!pcs)
>  			continue;
>
> -		mdio_device_free(pcs->mdio);
> +		mdio_device_free(lynx_pcs_get_mdio(pcs));

Don't really have a better suggestion than lynx_pcs_get_mdio.

>  		lynx_pcs_destroy(pcs);
>  	}
>  	felix_mdio_bus_free(ocelot);
> diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> index ccaf7e35abeb..484f0d4efefe 100644
> --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> @@ -270,10 +270,11 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
>
>  static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
>  {
> -	struct lynx_pcs *pcs = mac->pcs;
> +	struct phylink_pcs *pcs = mac->pcs;
>
>  	if (pcs) {
> -		struct device *dev = &pcs->mdio->dev;
> +		struct mdio_device *mdio = lynx_get_mdio_device(pcs);
> +		struct device *dev = &mdio->dev;
>  		lynx_pcs_destroy(pcs);
>  		put_device(dev);

Ideally dpaa2 would call mdio_device_free too, just like the others.

>  		mac->pcs = NULL;
> @@ -336,7 +337,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
>  	mac->phylink = phylink;
>
>  	if (mac->pcs)
> -		phylink_set_pcs(mac->phylink, &mac->pcs->pcs);
> +		phylink_set_pcs(mac->phylink, mac->pcs);
>
>  	err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
>  	if (err) {
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
> index 31274325159a..cc2ca51ac984 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
> @@ -823,7 +823,7 @@ static int enetc_imdio_create(struct enetc_pf *pf)
>  {
>  	struct device *dev = &pf->si->pdev->dev;
>  	struct enetc_mdio_priv *mdio_priv;
> -	struct lynx_pcs *pcs_lynx;
> +	struct phylink_pcs *pcs_phylink;
>  	struct mdio_device *pcs;

Agree with Russell's suggestion to replace "pcs" with "mdiodev" wherever
it refers to a struct mdio_device. Likely as a separate patch.

>  	struct mii_bus *bus;
>  	int err;
> @@ -341,13 +355,13 @@ struct lynx_pcs *lynx_pcs_create(struct mdio_device *mdio)
>  	lynx_pcs->pcs.ops = &lynx_pcs_phylink_ops;
>  	lynx_pcs->pcs.poll = true;
>
> -	return lynx_pcs;
> +	return lynx_to_phylink_pcs(lynx_pcs);

I would probably write another patch to convert all occurrences of
"struct lynx_pcs" variables to the same naming scheme. Currently we have
"lynx", "pcs", "lynx_pcs" only within the pcs-lynx.c file itself. "lynx"
seems to be the predominant name so all others could be replaced with
that too.

>  }
>  EXPORT_SYMBOL(lynx_pcs_create);
>
> -void lynx_pcs_destroy(struct lynx_pcs *pcs)
> +void lynx_pcs_destroy(struct phylink_pcs *pcs)
>  {
> -	kfree(pcs);
> +	kfree(phylink_pcs_to_lynx(pcs));

I would perhaps do this in two stages

	struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);

	kfree(lynx);

>  }
>  EXPORT_SYMBOL(lynx_pcs_destroy);
>
> diff --git a/include/linux/pcs-lynx.h b/include/linux/pcs-lynx.h
> index a6440d6ebe95..5712cc2ce775 100644
> --- a/include/linux/pcs-lynx.h
> +++ b/include/linux/pcs-lynx.h
> @@ -9,13 +9,10 @@
>  #include <linux/mdio.h>
>  #include <linux/phylink.h>
>
> -struct lynx_pcs {
> -	struct phylink_pcs pcs;
> -	struct mdio_device *mdio;
> -};

Good that this structure is no longer exposed.

> +struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs);
>
> -struct lynx_pcs *lynx_pcs_create(struct mdio_device *mdio);
> +struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio);
>
> -void lynx_pcs_destroy(struct lynx_pcs *pcs);
> +void lynx_pcs_destroy(struct phylink_pcs *pcs);

We don't want the few phylink_pcs drivers going in different directions,
so we should modify pcs-xpcs.c too such that it no longer exposes struct
dw_xpcs to the outside world. I think I hid most of that away already,
and grepping for "xpcs->" in drivers/net/dsa and drivers/net/ethernet,
I only see xpcs->mdiodev and xpcs->pcs being accessed, so converting
khat should be a walk in the park.

Anyway, I would focus for now on getting the ocelot hardware to work and
writing the phylink_pcs driver for that. That is one part where I can't
help a lot with.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
  2021-08-14  2:50 ` [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device Colin Foster
  2021-08-14 11:47   ` Vladimir Oltean
@ 2021-08-17 22:08   ` Rob Herring
  1 sibling, 0 replies; 36+ messages in thread
From: Rob Herring @ 2021-08-17 22:08 UTC (permalink / raw)
  To: Colin Foster
  Cc: andrew, vivien.didelot, f.fainelli, olteanv, davem, kuba,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Fri, Aug 13, 2021 at 07:50:03PM -0700, Colin Foster wrote:
> Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> ---
>  .../devicetree/bindings/net/dsa/ocelot.txt    | 92 +++++++++++++++++++
>  1 file changed, 92 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/net/dsa/ocelot.txt b/Documentation/devicetree/bindings/net/dsa/ocelot.txt
> index 7a271d070b72..edf560a50803 100644
> --- a/Documentation/devicetree/bindings/net/dsa/ocelot.txt
> +++ b/Documentation/devicetree/bindings/net/dsa/ocelot.txt
> @@ -8,6 +8,7 @@ Currently the switches supported by the felix driver are:
>  
>  - VSC9959 (Felix)
>  - VSC9953 (Seville)
> +- VSC7511, VSC7512, VSC7513, VSC7514 via SPI
>  
>  The VSC9959 switch is found in the NXP LS1028A. It is a PCI device, part of the
>  larger ENETC root complex. As a result, the ethernet-switch node is a sub-node
> @@ -211,3 +212,94 @@ Example:
>  		};
>  	};
>  };
> +
> +The VSC7513 and VSC7514 switches can be controlled internally via the MIPS
> +processor. The VSC7511 and VSC7512 don't have this internal processor, but all
> +four chips can be controlled externally through SPI with the following required
> +properties:
> +
> +- compatible:
> +	Can be "mscc,vsc7511", "mscc,vsc7512", "mscc,vsc7513", or
> +	"mscc,vsc7514".
> +
> +Supported phy modes for all chips are:
> +
> +* phy_mode = "sgmii": on ports 0, 1, 2, 3
> +
> +The VSC7512 and 7514 also support:
> +
> +* phy_mode = "sgmii": on ports 4, 5, 6, 7
> +* phy_mode = "qsgmii": on ports 7, 8, 10
> +
> +Example for control from a BeagleBone Black
> +
> +&spi0 {
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	ethernet-switch@0 {
> +		compatible = "mscc,vsc7512";
> +		spi-max-frequency = <250000>;
> +		reg = <0>;
> +
> +		ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			port@0 {
> +				reg = <0>;
> +				ethernet = <&mac>;
> +				phy-mode = "sgmii";
> +
> +				fixed-link {
> +					speed = <100>;
> +					full-duplex;
> +				};
> +			};
> +
> +			port@1 {
> +				reg = <1>;
> +				label = "swp1";
> +				phy-handle = <&sw_phy1>;
> +				phy-mode = "sgmii";
> +			};
> +
> +			port@2 {
> +				reg = <2>;
> +				label = "swp2";
> +				phy-handle = <&sw_phy2>;
> +				phy-mode = "sgmii";
> +			};
> +
> +			port@3 {
> +				reg = <3>;
> +				label = "swp3";
> +				phy-handle = <&sw_phy3>;
> +				phy-mode = "sgmii";
> +			};
> +		};
> +
> +		mdio {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			sw_phy1: ethernet-phy@1 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0x1>;
> +			};
> +
> +			sw_phy2: ethernet-phy@2 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0x2>;
> +			};
> +
> +			sw_phy3: ethernet-phy@3 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0x3>;
> +			};
> +		};
> +	};
> +};

If you want a whole new example, then convert this to DT schema. But is 
there anything really new or different here to warrant another example?

Rob

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation
  2021-08-14 11:03   ` Vladimir Oltean
@ 2021-08-20 16:53     ` Colin Foster
  0 siblings, 0 replies; 36+ messages in thread
From: Colin Foster @ 2021-08-20 16:53 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: andrew, vivien.didelot, f.fainelli, davem, kuba, robh+dt,
	claudiu.manoil, alexandre.belloni, UNGLinuxDriver, hkallweit1,
	linux, netdev, devicetree, linux-kernel

On Sat, Aug 14, 2021 at 02:03:28PM +0300, Vladimir Oltean wrote:
> On Fri, Aug 13, 2021 at 07:49:55PM -0700, Colin Foster wrote:
> > Utilize regmap instead of __iomem to perform indirect mdio access. This
> > will allow for custom regmaps to be used by way of the mscc_miim_setup
> > function.
> > 
> > Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
> > ---
> 
> git b4 20210814025003.2449143-1-colin.foster@in-advantage.com
> Looking up https://lore.kernel.org/r/20210814025003.2449143-1-colin.foster%40in-advantage.com
> Grabbing thread from lore.kernel.org/linux-devicetree/20210814025003.2449143-1-colin.foster%40in-advantage.com/t.mbox.gz
> Analyzing 11 messages in the thread
> Checking attestation on all messages, may take a moment...
> ---
>   ✓ [PATCH RFC v3 1/10] net: dsa: ocelot: remove unnecessary pci_bar variables
>   ✓ [PATCH RFC v3 2/10] net: mdio: mscc-miim: convert to a regmap implementation
>   ✓ [PATCH RFC v3 3/10] net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect mdio access
>   ✓ [PATCH RFC v3 4/10] net: dsa: ocelot: felix: Remove requirement for PCS in felix devices
>   ✓ [PATCH RFC v3 5/10] net: dsa: ocelot: felix: add interface for custom regmaps
>   ✓ [PATCH RFC v3 6/10] net: mscc: ocelot: split register definitions to a separate file
>   ✓ [PATCH RFC v3 7/10] net: mscc: ocelot: expose ocelot wm functions
>   ✓ [PATCH RFC v3 8/10] net: mscc: ocelot: felix: add ability to enable a CPU / NPI port
>   ✓ [PATCH RFC v3 9/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI
>   ✓ [PATCH RFC v3 10/10] docs: devicetree: add documentation for the VSC7512 SPI device
>   ---
>   ✓ Signed: DKIM/inadvantage.onmicrosoft.com (From: colin.foster@in-advantage.com)
> ---
> Total patches: 10
> ---
>  Link: https://lore.kernel.org/r/20210814025003.2449143-1-colin.foster@in-advantage.com
>  Base: not found
> Applying: net: dsa: ocelot: remove unnecessary pci_bar variables
> Applying: net: mdio: mscc-miim: convert to a regmap implementation
> Using index info to reconstruct a base tree...
> M       drivers/net/mdio/mdio-mscc-miim.c
> Falling back to patching base and 3-way merge...
> Auto-merging drivers/net/mdio/mdio-mscc-miim.c
> CONFLICT (content): Merge conflict in drivers/net/mdio/mdio-mscc-miim.c
> error: Failed to merge in the changes.
> Patch failed at 0002 net: mdio: mscc-miim: convert to a regmap implementation
> hint: Use 'git am --show-current-patch' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".

I see what happened here. I had my branch on the latest 5.13 tag of
net-next and it conflicts with the master. Makes sense.

I should have rebased onto V5.14-rc5 (the latest at the time) before 
submitting. A mistake I'll hopefully only make this once.

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2021-08-20 16:53 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-14  2:49 [RFC PATCH v3 net-next 00/10] add support for VSC75XX control over SPI Colin Foster
2021-08-14  2:49 ` [RFC PATCH v3 net-next 01/10] net: dsa: ocelot: remove unnecessary pci_bar variables Colin Foster
2021-08-14 11:07   ` Vladimir Oltean
2021-08-14 16:26     ` Colin Foster
2021-08-14  2:49 ` [RFC PATCH v3 net-next 02/10] net: mdio: mscc-miim: convert to a regmap implementation Colin Foster
2021-08-14 11:03   ` Vladimir Oltean
2021-08-20 16:53     ` Colin Foster
2021-08-14  2:49 ` [RFC PATCH v3 net-next 03/10] net: dsa: ocelot: felix: switch to mdio-mscc-miim driver for indirect mdio access Colin Foster
2021-08-14  2:49 ` [RFC PATCH v3 net-next 04/10] net: dsa: ocelot: felix: Remove requirement for PCS in felix devices Colin Foster
2021-08-14  2:49 ` [RFC PATCH v3 net-next 05/10] net: dsa: ocelot: felix: add interface for custom regmaps Colin Foster
2021-08-14  2:49 ` [RFC PATCH v3 net-next 06/10] net: mscc: ocelot: split register definitions to a separate file Colin Foster
2021-08-14 11:15   ` Vladimir Oltean
2021-08-14 16:33     ` Colin Foster
2021-08-14 16:56   ` Alexandre Belloni
2021-08-14  2:50 ` [RFC PATCH v3 net-next 07/10] net: mscc: ocelot: expose ocelot wm functions Colin Foster
2021-08-14 11:17   ` Vladimir Oltean
2021-08-14 16:36     ` Colin Foster
2021-08-14  2:50 ` [RFC PATCH v3 net-next 08/10] net: mscc: ocelot: felix: add ability to enable a CPU / NPI port Colin Foster
2021-08-14  2:50 ` [RFC PATCH v3 net-next 09/10] net: dsa: ocelot: felix: add support for VSC75XX control over SPI Colin Foster
2021-08-14 11:43   ` Vladimir Oltean
2021-08-14 12:02     ` Vladimir Oltean
2021-08-15 19:10       ` Colin Foster
2021-08-15 20:41       ` Colin Foster
2021-08-15 23:14         ` Russell King (Oracle)
2021-08-15 23:27           ` Colin Foster
2021-08-16  0:05             ` Russell King (Oracle)
2021-08-17  9:41         ` Vladimir Oltean
2021-08-15 21:35       ` Russell King (Oracle)
2021-08-14  2:50 ` [RFC PATCH v3 net-next 10/10] docs: devicetree: add documentation for the VSC7512 SPI device Colin Foster
2021-08-14 11:47   ` Vladimir Oltean
2021-08-14 18:40     ` Colin Foster
2021-08-14 19:08       ` Vladimir Oltean
2021-08-14 23:41         ` Colin Foster
2021-08-15  0:00           ` Vladimir Oltean
2021-08-15  1:08             ` Colin Foster
2021-08-17 22:08   ` Rob Herring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).