All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch
@ 2020-05-27 23:41 Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization Vladimir Oltean
                   ` (11 more replies)
  0 siblings, 12 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

Looking at the Felix and Ocelot drivers, Maxim asked if it would be
possible to use them as a base for a new driver for the switch inside
NXP T1040. Turns out, it is! The result is a driver eerily similar to
Felix.

The biggest challenge seems to be getting register read/write API
generic enough to cover such wild bitfield variations between hardware
generations. There is a patch on the regmap core which I would like to
get in through the networking subsystem, if possible (and if Mark is
ok), since it's a trivial addition.

Maxim Kochetkov (4):
  soc/mscc: ocelot: add MII registers description
  net: mscc: ocelot: convert SYS_PAUSE_CFG register access to regfield
  net: mscc: ocelot: extend watermark encoding function
  net: dsa: ocelot: introduce driver for Seville VSC9953 switch

Vladimir Oltean (7):
  regmap: add helper for per-port regfield initialization
  net: mscc: ocelot: unexport ocelot_probe_port
  net: mscc: ocelot: convert port registers to regmap
  net: mscc: ocelot: convert QSYS_SWITCH_PORT_MODE and SYS_PORT_MODE to
    regfields
  net: dsa: ocelot: create a template for the DSA tags on xmit
  net: mscc: ocelot: split writes to pause frame enable bit and to
    thresholds
  net: mscc: ocelot: disable flow control on NPI interface

 drivers/net/dsa/ocelot/Kconfig           |   12 +
 drivers/net/dsa/ocelot/Makefile          |    6 +
 drivers/net/dsa/ocelot/felix.c           |   49 +-
 drivers/net/dsa/ocelot/felix_vsc9959.c   |   72 +-
 drivers/net/dsa/ocelot/seville.c         |  742 +++++++++++++++
 drivers/net/dsa/ocelot/seville.h         |   50 +
 drivers/net/dsa/ocelot/seville_vsc9953.c | 1064 ++++++++++++++++++++++
 drivers/net/ethernet/mscc/ocelot.c       |   87 +-
 drivers/net/ethernet/mscc/ocelot.h       |    9 +-
 drivers/net/ethernet/mscc/ocelot_board.c |   21 +-
 drivers/net/ethernet/mscc/ocelot_io.c    |   18 +-
 drivers/net/ethernet/mscc/ocelot_regs.c  |   57 ++
 include/linux/regmap.h                   |    8 +
 include/soc/mscc/ocelot.h                |   68 +-
 include/soc/mscc/ocelot_dev.h            |   78 --
 include/soc/mscc/ocelot_qsys.h           |   13 -
 include/soc/mscc/ocelot_sys.h            |   23 -
 net/dsa/tag_ocelot.c                     |   21 +-
 18 files changed, 2196 insertions(+), 202 deletions(-)
 create mode 100644 drivers/net/dsa/ocelot/seville.c
 create mode 100644 drivers/net/dsa/ocelot/seville.h
 create mode 100644 drivers/net/dsa/ocelot/seville_vsc9953.c

-- 
2.25.1


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

* [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:46   ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port Vladimir Oltean
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Similar to the standalone regfields, add an initializer for the users
who need to set .id_size and .id_offset in order to use the
regmap_fields_update_bits_base API.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/linux/regmap.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 40b07168fd8e..87703d105191 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1134,6 +1134,14 @@ struct reg_field {
 				.msb = _msb,	\
 				}
 
+#define REG_FIELD_ID(_reg, _lsb, _msb, _size, _offset) {	\
+				.reg = _reg,			\
+				.lsb = _lsb,			\
+				.msb = _msb,			\
+				.id_size = _size,		\
+				.id_offset = _offset,		\
+				}
+
 struct regmap_field *regmap_field_alloc(struct regmap *regmap,
 		struct reg_field reg_field);
 void regmap_field_free(struct regmap_field *field);
-- 
2.25.1


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

* [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-28 16:21   ` Jakub Kicinski
  2020-05-27 23:41 ` [PATCH net-next 03/11] net: mscc: ocelot: convert port registers to regmap Vladimir Oltean
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

This is not being used by any other module except ocelot (i.e. felix
does not use it). So remove the EXPORT_SYMBOL.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index e621c4c3ee86..ff875c2f1d46 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2152,7 +2152,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 
 	return err;
 }
-EXPORT_SYMBOL(ocelot_probe_port);
 
 /* Configure and enable the CPU port module, which is a set of queues.
  * If @npi contains a valid port index, the CPU port module is connected
-- 
2.25.1


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

* [PATCH net-next 03/11] net: mscc: ocelot: convert port registers to regmap
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 04/11] soc/mscc: ocelot: add MII registers description Vladimir Oltean
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

At the moment, there are some minimal register differences between
VSC7514 Ocelot and VSC9959 Felix. To be precise, the PCS1G registers are
missing from Felix because it was integrated with an NXP PCS.

But with VSC9953 Seville (not yet introduced), the register differences
are more pronounced.  The MAC registers are located at different offsets
within the DEV_GMII target. So we need to refactor the driver to keep a
regmap even for per-port registers. The callers of the ocelot_port_readl
and ocelot_port_writel were kept unchanged, only the implementation is
now more generic.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c           | 13 ++--
 drivers/net/dsa/ocelot/felix_vsc9959.c   | 45 +++++++++++++-
 drivers/net/ethernet/mscc/ocelot.c       |  5 +-
 drivers/net/ethernet/mscc/ocelot.h       |  3 +-
 drivers/net/ethernet/mscc/ocelot_board.c |  8 +--
 drivers/net/ethernet/mscc/ocelot_io.c    | 16 ++++-
 drivers/net/ethernet/mscc/ocelot_regs.c  | 43 +++++++++++++
 include/soc/mscc/ocelot.h                | 42 ++++++++++++-
 include/soc/mscc/ocelot_dev.h            | 78 ------------------------
 9 files changed, 156 insertions(+), 97 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index a6e272d2110d..13722cde503e 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -478,7 +478,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 
 	for (port = 0; port < num_phys_ports; port++) {
 		struct ocelot_port *ocelot_port;
-		void __iomem *port_regs;
+		struct regmap *target;
 
 		ocelot_port = devm_kzalloc(ocelot->dev,
 					   sizeof(struct ocelot_port),
@@ -495,17 +495,18 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 		res.start += switch_base;
 		res.end += switch_base;
 
-		port_regs = devm_ioremap_resource(ocelot->dev, &res);
-		if (IS_ERR(port_regs)) {
+		target = ocelot_regmap_init(ocelot, &res);
+		if (IS_ERR(target)) {
 			dev_err(ocelot->dev,
-				"failed to map registers for port %d\n", port);
+				"Failed to map memory space for port %d\n",
+				port);
 			kfree(port_phy_modes);
-			return PTR_ERR(port_regs);
+			return PTR_ERR(target);
 		}
 
 		ocelot_port->phy_mode = port_phy_modes[port];
 		ocelot_port->ocelot = ocelot;
-		ocelot_port->regs = port_regs;
+		ocelot_port->target = target;
 		ocelot->ports[port] = ocelot_port;
 	}
 
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 1dd9e348152d..dda7a3a7aa6f 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -329,6 +329,48 @@ static const u32 vsc9959_gcb_regmap[] = {
 	REG(GCB_SOFT_RST,			0x000004),
 };
 
+static const u32 vsc9959_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_RESERVED(PCS1G_CFG),
+	REG_RESERVED(PCS1G_MODE_CFG),
+	REG_RESERVED(PCS1G_SD_CFG),
+	REG_RESERVED(PCS1G_ANEG_CFG),
+	REG_RESERVED(PCS1G_ANEG_NP_CFG),
+	REG_RESERVED(PCS1G_LB_CFG),
+	REG_RESERVED(PCS1G_DBG_CFG),
+	REG_RESERVED(PCS1G_CDET_CFG),
+	REG_RESERVED(PCS1G_ANEG_STATUS),
+	REG_RESERVED(PCS1G_ANEG_NP_STATUS),
+	REG_RESERVED(PCS1G_LINK_STATUS),
+	REG_RESERVED(PCS1G_LINK_DOWN_CNT),
+	REG_RESERVED(PCS1G_STICKY),
+	REG_RESERVED(PCS1G_DEBUG_STATUS),
+	REG_RESERVED(PCS1G_LPI_CFG),
+	REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT),
+	REG_RESERVED(PCS1G_LPI_STATUS),
+	REG_RESERVED(PCS1G_TSTPAT_MODE_CFG),
+	REG_RESERVED(PCS1G_TSTPAT_STATUS),
+	REG_RESERVED(DEV_PCS_FX100_CFG),
+	REG_RESERVED(DEV_PCS_FX100_STATUS),
+};
+
 static const u32 *vsc9959_regmap[] = {
 	[ANA]	= vsc9959_ana_regmap,
 	[QS]	= vsc9959_qs_regmap,
@@ -338,10 +380,11 @@ static const u32 *vsc9959_regmap[] = {
 	[S2]	= vsc9959_s2_regmap,
 	[PTP]	= vsc9959_ptp_regmap,
 	[GCB]	= vsc9959_gcb_regmap,
+	[DEV_GMII] = vsc9959_dev_gmii_regmap,
 };
 
 /* Addresses are relative to the PCI device's base address */
-static const struct resource vsc9959_target_io_res[] = {
+static const struct resource vsc9959_target_io_res[TARGET_MAX] = {
 	[ANA] = {
 		.start	= 0x0280000,
 		.end	= 0x028ffff,
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index ff875c2f1d46..d5bfa6d3e73c 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2108,8 +2108,7 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
 }
 EXPORT_SYMBOL(ocelot_init_port);
 
-int ocelot_probe_port(struct ocelot *ocelot, u8 port,
-		      void __iomem *regs,
+int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
 		      struct phy_device *phy)
 {
 	struct ocelot_port_private *priv;
@@ -2127,7 +2126,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 	priv->chip_port = port;
 	ocelot_port = &priv->port;
 	ocelot_port->ocelot = ocelot;
-	ocelot_port->regs = regs;
+	ocelot_port->target = target;
 	ocelot->ports[port] = ocelot_port;
 
 	dev->netdev_ops = &ocelot_port_netdev_ops;
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index f0a15aa187f2..b22997dd098e 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -67,8 +67,7 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
 #define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
 
 int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops);
-int ocelot_probe_port(struct ocelot *ocelot, u8 port,
-		      void __iomem *regs,
+int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
 		      struct phy_device *phy);
 
 void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 67a8d61c926a..b6ea9694c3ae 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -505,9 +505,9 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 		struct device_node *phy_node;
 		phy_interface_t phy_mode;
 		struct phy_device *phy;
+		struct regmap *target;
 		struct resource *res;
 		struct phy *serdes;
-		void __iomem *regs;
 		char res_name[8];
 		u32 port;
 
@@ -518,8 +518,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   res_name);
-		regs = devm_ioremap_resource(&pdev->dev, res);
-		if (IS_ERR(regs))
+		target = ocelot_regmap_init(ocelot, res);
+		if (IS_ERR(target))
 			continue;
 
 		phy_node = of_parse_phandle(portnp, "phy-handle", 0);
@@ -531,7 +531,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 		if (!phy)
 			continue;
 
-		err = ocelot_probe_port(ocelot, port, regs, phy);
+		err = ocelot_probe_port(ocelot, port, target, phy);
 		if (err) {
 			of_node_put(portnp);
 			goto out_put_ports;
diff --git a/drivers/net/ethernet/mscc/ocelot_io.c b/drivers/net/ethernet/mscc/ocelot_io.c
index b229b1cb68ef..741f653bc85b 100644
--- a/drivers/net/ethernet/mscc/ocelot_io.c
+++ b/drivers/net/ethernet/mscc/ocelot_io.c
@@ -49,13 +49,25 @@ EXPORT_SYMBOL(__ocelot_rmw_ix);
 
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
 {
-	return readl(port->regs + reg);
+	struct ocelot *ocelot = port->ocelot;
+	u16 target = reg >> TARGET_OFFSET;
+	u32 val;
+
+	WARN_ON(!target);
+
+	regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
+	return val;
 }
 EXPORT_SYMBOL(ocelot_port_readl);
 
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
 {
-	writel(val, port->regs + reg);
+	struct ocelot *ocelot = port->ocelot;
+	u16 target = reg >> TARGET_OFFSET;
+
+	WARN_ON(!target);
+
+	regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
 }
 EXPORT_SYMBOL(ocelot_port_writel);
 
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index 81d81ff75646..18d73b4e5cb5 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -246,6 +246,48 @@ static const u32 ocelot_ptp_regmap[] = {
 	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[] = {
 	[ANA] = ocelot_ana_regmap,
 	[QS] = ocelot_qs_regmap,
@@ -254,6 +296,7 @@ static const u32 *ocelot_regmap[] = {
 	[SYS] = ocelot_sys_regmap,
 	[S2] = ocelot_s2_regmap,
 	[PTP] = ocelot_ptp_regmap,
+	[DEV_GMII] = ocelot_dev_gmii_regmap,
 };
 
 static const struct reg_field ocelot_regfields[] = {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 4953e9994df3..79c77aab87e5 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -111,6 +111,7 @@ enum ocelot_target {
 	HSIO,
 	PTP,
 	GCB,
+	DEV_GMII,
 	TARGET_MAX,
 };
 
@@ -393,6 +394,45 @@ enum ocelot_reg {
 	PTP_CLK_CFG_ADJ_CFG,
 	PTP_CLK_CFG_ADJ_FREQ,
 	GCB_SOFT_RST = GCB << TARGET_OFFSET,
+	DEV_CLOCK_CFG = DEV_GMII << TARGET_OFFSET,
+	DEV_PORT_MISC,
+	DEV_EVENTS,
+	DEV_EEE_CFG,
+	DEV_RX_PATH_DELAY,
+	DEV_TX_PATH_DELAY,
+	DEV_PTP_PREDICT_CFG,
+	DEV_MAC_ENA_CFG,
+	DEV_MAC_MODE_CFG,
+	DEV_MAC_MAXLEN_CFG,
+	DEV_MAC_TAGS_CFG,
+	DEV_MAC_ADV_CHK_CFG,
+	DEV_MAC_IFG_CFG,
+	DEV_MAC_HDX_CFG,
+	DEV_MAC_DBG_CFG,
+	DEV_MAC_FC_MAC_LOW_CFG,
+	DEV_MAC_FC_MAC_HIGH_CFG,
+	DEV_MAC_STICKY,
+	PCS1G_CFG,
+	PCS1G_MODE_CFG,
+	PCS1G_SD_CFG,
+	PCS1G_ANEG_CFG,
+	PCS1G_ANEG_NP_CFG,
+	PCS1G_LB_CFG,
+	PCS1G_DBG_CFG,
+	PCS1G_CDET_CFG,
+	PCS1G_ANEG_STATUS,
+	PCS1G_ANEG_NP_STATUS,
+	PCS1G_LINK_STATUS,
+	PCS1G_LINK_DOWN_CNT,
+	PCS1G_STICKY,
+	PCS1G_DEBUG_STATUS,
+	PCS1G_LPI_CFG,
+	PCS1G_LPI_WAKE_ERROR_CNT,
+	PCS1G_LPI_STATUS,
+	PCS1G_TSTPAT_MODE_CFG,
+	PCS1G_TSTPAT_STATUS,
+	DEV_PCS_FX100_CFG,
+	DEV_PCS_FX100_STATUS,
 };
 
 enum ocelot_regfield {
@@ -479,7 +519,7 @@ struct ocelot_acl_block {
 struct ocelot_port {
 	struct ocelot			*ocelot;
 
-	void __iomem			*regs;
+	struct regmap			*target;
 
 	bool				vlan_aware;
 
diff --git a/include/soc/mscc/ocelot_dev.h b/include/soc/mscc/ocelot_dev.h
index 7c08437061fc..0c6021f02fee 100644
--- a/include/soc/mscc/ocelot_dev.h
+++ b/include/soc/mscc/ocelot_dev.h
@@ -8,8 +8,6 @@
 #ifndef _MSCC_OCELOT_DEV_H_
 #define _MSCC_OCELOT_DEV_H_
 
-#define DEV_CLOCK_CFG                                     0x0
-
 #define DEV_CLOCK_CFG_MAC_TX_RST                          BIT(7)
 #define DEV_CLOCK_CFG_MAC_RX_RST                          BIT(6)
 #define DEV_CLOCK_CFG_PCS_TX_RST                          BIT(5)
@@ -19,18 +17,12 @@
 #define DEV_CLOCK_CFG_LINK_SPEED(x)                       ((x) & GENMASK(1, 0))
 #define DEV_CLOCK_CFG_LINK_SPEED_M                        GENMASK(1, 0)
 
-#define DEV_PORT_MISC                                     0x4
-
 #define DEV_PORT_MISC_FWD_ERROR_ENA                       BIT(4)
 #define DEV_PORT_MISC_FWD_PAUSE_ENA                       BIT(3)
 #define DEV_PORT_MISC_FWD_CTRL_ENA                        BIT(2)
 #define DEV_PORT_MISC_DEV_LOOP_ENA                        BIT(1)
 #define DEV_PORT_MISC_HDX_FAST_DIS                        BIT(0)
 
-#define DEV_EVENTS                                        0x8
-
-#define DEV_EEE_CFG                                       0xc
-
 #define DEV_EEE_CFG_EEE_ENA                               BIT(22)
 #define DEV_EEE_CFG_EEE_TIMER_AGE(x)                      (((x) << 15) & GENMASK(21, 15))
 #define DEV_EEE_CFG_EEE_TIMER_AGE_M                       GENMASK(21, 15)
@@ -43,33 +35,19 @@
 #define DEV_EEE_CFG_EEE_TIMER_HOLDOFF_X(x)                (((x) & GENMASK(7, 1)) >> 1)
 #define DEV_EEE_CFG_PORT_LPI                              BIT(0)
 
-#define DEV_RX_PATH_DELAY                                 0x10
-
-#define DEV_TX_PATH_DELAY                                 0x14
-
-#define DEV_PTP_PREDICT_CFG                               0x18
-
 #define DEV_PTP_PREDICT_CFG_PTP_PHY_PREDICT_CFG(x)        (((x) << 4) & GENMASK(11, 4))
 #define DEV_PTP_PREDICT_CFG_PTP_PHY_PREDICT_CFG_M         GENMASK(11, 4)
 #define DEV_PTP_PREDICT_CFG_PTP_PHY_PREDICT_CFG_X(x)      (((x) & GENMASK(11, 4)) >> 4)
 #define DEV_PTP_PREDICT_CFG_PTP_PHASE_PREDICT_CFG(x)      ((x) & GENMASK(3, 0))
 #define DEV_PTP_PREDICT_CFG_PTP_PHASE_PREDICT_CFG_M       GENMASK(3, 0)
 
-#define DEV_MAC_ENA_CFG                                   0x1c
-
 #define DEV_MAC_ENA_CFG_RX_ENA                            BIT(4)
 #define DEV_MAC_ENA_CFG_TX_ENA                            BIT(0)
 
-#define DEV_MAC_MODE_CFG                                  0x20
-
 #define DEV_MAC_MODE_CFG_FC_WORD_SYNC_ENA                 BIT(8)
 #define DEV_MAC_MODE_CFG_GIGA_MODE_ENA                    BIT(4)
 #define DEV_MAC_MODE_CFG_FDX_ENA                          BIT(0)
 
-#define DEV_MAC_MAXLEN_CFG                                0x24
-
-#define DEV_MAC_TAGS_CFG                                  0x28
-
 #define DEV_MAC_TAGS_CFG_TAG_ID(x)                        (((x) << 16) & GENMASK(31, 16))
 #define DEV_MAC_TAGS_CFG_TAG_ID_M                         GENMASK(31, 16)
 #define DEV_MAC_TAGS_CFG_TAG_ID_X(x)                      (((x) & GENMASK(31, 16)) >> 16)
@@ -77,12 +55,8 @@
 #define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA                 BIT(1)
 #define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA                     BIT(0)
 
-#define DEV_MAC_ADV_CHK_CFG                               0x2c
-
 #define DEV_MAC_ADV_CHK_CFG_LEN_DROP_ENA                  BIT(0)
 
-#define DEV_MAC_IFG_CFG                                   0x30
-
 #define DEV_MAC_IFG_CFG_RESTORE_OLD_IPG_CHECK             BIT(17)
 #define DEV_MAC_IFG_CFG_REDUCED_TX_IFG                    BIT(16)
 #define DEV_MAC_IFG_CFG_TX_IFG(x)                         (((x) << 8) & GENMASK(12, 8))
@@ -94,8 +68,6 @@
 #define DEV_MAC_IFG_CFG_RX_IFG1(x)                        ((x) & GENMASK(3, 0))
 #define DEV_MAC_IFG_CFG_RX_IFG1_M                         GENMASK(3, 0)
 
-#define DEV_MAC_HDX_CFG                                   0x34
-
 #define DEV_MAC_HDX_CFG_BYPASS_COL_SYNC                   BIT(26)
 #define DEV_MAC_HDX_CFG_OB_ENA                            BIT(25)
 #define DEV_MAC_HDX_CFG_WEXC_DIS                          BIT(24)
@@ -107,17 +79,9 @@
 #define DEV_MAC_HDX_CFG_LATE_COL_POS(x)                   ((x) & GENMASK(6, 0))
 #define DEV_MAC_HDX_CFG_LATE_COL_POS_M                    GENMASK(6, 0)
 
-#define DEV_MAC_DBG_CFG                                   0x38
-
 #define DEV_MAC_DBG_CFG_TBI_MODE                          BIT(4)
 #define DEV_MAC_DBG_CFG_IFG_CRS_EXT_CHK_ENA               BIT(0)
 
-#define DEV_MAC_FC_MAC_LOW_CFG                            0x3c
-
-#define DEV_MAC_FC_MAC_HIGH_CFG                           0x40
-
-#define DEV_MAC_STICKY                                    0x44
-
 #define DEV_MAC_STICKY_RX_IPG_SHRINK_STICKY               BIT(9)
 #define DEV_MAC_STICKY_RX_PREAM_SHRINK_STICKY             BIT(8)
 #define DEV_MAC_STICKY_RX_CARRIER_EXT_STICKY              BIT(7)
@@ -129,25 +93,17 @@
 #define DEV_MAC_STICKY_TX_FRM_LEN_OVR_STICKY              BIT(1)
 #define DEV_MAC_STICKY_TX_ABORT_STICKY                    BIT(0)
 
-#define PCS1G_CFG                                         0x48
-
 #define PCS1G_CFG_LINK_STATUS_TYPE                        BIT(4)
 #define PCS1G_CFG_AN_LINK_CTRL_ENA                        BIT(1)
 #define PCS1G_CFG_PCS_ENA                                 BIT(0)
 
-#define PCS1G_MODE_CFG                                    0x4c
-
 #define PCS1G_MODE_CFG_UNIDIR_MODE_ENA                    BIT(4)
 #define PCS1G_MODE_CFG_SGMII_MODE_ENA                     BIT(0)
 
-#define PCS1G_SD_CFG                                      0x50
-
 #define PCS1G_SD_CFG_SD_SEL                               BIT(8)
 #define PCS1G_SD_CFG_SD_POL                               BIT(4)
 #define PCS1G_SD_CFG_SD_ENA                               BIT(0)
 
-#define PCS1G_ANEG_CFG                                    0x54
-
 #define PCS1G_ANEG_CFG_ADV_ABILITY(x)                     (((x) << 16) & GENMASK(31, 16))
 #define PCS1G_ANEG_CFG_ADV_ABILITY_M                      GENMASK(31, 16)
 #define PCS1G_ANEG_CFG_ADV_ABILITY_X(x)                   (((x) & GENMASK(31, 16)) >> 16)
@@ -155,29 +111,19 @@
 #define PCS1G_ANEG_CFG_ANEG_RESTART_ONE_SHOT              BIT(1)
 #define PCS1G_ANEG_CFG_ANEG_ENA                           BIT(0)
 
-#define PCS1G_ANEG_NP_CFG                                 0x58
-
 #define PCS1G_ANEG_NP_CFG_NP_TX(x)                        (((x) << 16) & GENMASK(31, 16))
 #define PCS1G_ANEG_NP_CFG_NP_TX_M                         GENMASK(31, 16)
 #define PCS1G_ANEG_NP_CFG_NP_TX_X(x)                      (((x) & GENMASK(31, 16)) >> 16)
 #define PCS1G_ANEG_NP_CFG_NP_LOADED_ONE_SHOT              BIT(0)
 
-#define PCS1G_LB_CFG                                      0x5c
-
 #define PCS1G_LB_CFG_RA_ENA                               BIT(4)
 #define PCS1G_LB_CFG_GMII_PHY_LB_ENA                      BIT(1)
 #define PCS1G_LB_CFG_TBI_HOST_LB_ENA                      BIT(0)
 
-#define PCS1G_DBG_CFG                                     0x60
-
 #define PCS1G_DBG_CFG_UDLT                                BIT(0)
 
-#define PCS1G_CDET_CFG                                    0x64
-
 #define PCS1G_CDET_CFG_CDET_ENA                           BIT(0)
 
-#define PCS1G_ANEG_STATUS                                 0x68
-
 #define PCS1G_ANEG_STATUS_LP_ADV_ABILITY(x)               (((x) << 16) & GENMASK(31, 16))
 #define PCS1G_ANEG_STATUS_LP_ADV_ABILITY_M                GENMASK(31, 16)
 #define PCS1G_ANEG_STATUS_LP_ADV_ABILITY_X(x)             (((x) & GENMASK(31, 16)) >> 16)
@@ -185,10 +131,6 @@
 #define PCS1G_ANEG_STATUS_PAGE_RX_STICKY                  BIT(3)
 #define PCS1G_ANEG_STATUS_ANEG_COMPLETE                   BIT(0)
 
-#define PCS1G_ANEG_NP_STATUS                              0x6c
-
-#define PCS1G_LINK_STATUS                                 0x70
-
 #define PCS1G_LINK_STATUS_DELAY_VAR(x)                    (((x) << 12) & GENMASK(15, 12))
 #define PCS1G_LINK_STATUS_DELAY_VAR_M                     GENMASK(15, 12)
 #define PCS1G_LINK_STATUS_DELAY_VAR_X(x)                  (((x) & GENMASK(15, 12)) >> 12)
@@ -196,17 +138,9 @@
 #define PCS1G_LINK_STATUS_LINK_STATUS                     BIT(4)
 #define PCS1G_LINK_STATUS_SYNC_STATUS                     BIT(0)
 
-#define PCS1G_LINK_DOWN_CNT                               0x74
-
-#define PCS1G_STICKY                                      0x78
-
 #define PCS1G_STICKY_LINK_DOWN_STICKY                     BIT(4)
 #define PCS1G_STICKY_OUT_OF_SYNC_STICKY                   BIT(0)
 
-#define PCS1G_DEBUG_STATUS                                0x7c
-
-#define PCS1G_LPI_CFG                                     0x80
-
 #define PCS1G_LPI_CFG_QSGMII_MS_SEL                       BIT(20)
 #define PCS1G_LPI_CFG_RX_LPI_OUT_DIS                      BIT(17)
 #define PCS1G_LPI_CFG_LPI_TESTMODE                        BIT(16)
@@ -215,10 +149,6 @@
 #define PCS1G_LPI_CFG_LPI_RX_WTIM_X(x)                    (((x) & GENMASK(5, 4)) >> 4)
 #define PCS1G_LPI_CFG_TX_ASSERT_LPIDLE                    BIT(0)
 
-#define PCS1G_LPI_WAKE_ERROR_CNT                          0x84
-
-#define PCS1G_LPI_STATUS                                  0x88
-
 #define PCS1G_LPI_STATUS_RX_LPI_FAIL                      BIT(16)
 #define PCS1G_LPI_STATUS_RX_LPI_EVENT_STICKY              BIT(12)
 #define PCS1G_LPI_STATUS_RX_QUIET                         BIT(9)
@@ -227,18 +157,12 @@
 #define PCS1G_LPI_STATUS_TX_QUIET                         BIT(1)
 #define PCS1G_LPI_STATUS_TX_LPI_MODE                      BIT(0)
 
-#define PCS1G_TSTPAT_MODE_CFG                             0x8c
-
-#define PCS1G_TSTPAT_STATUS                               0x90
-
 #define PCS1G_TSTPAT_STATUS_JTP_ERR_CNT(x)                (((x) << 8) & GENMASK(15, 8))
 #define PCS1G_TSTPAT_STATUS_JTP_ERR_CNT_M                 GENMASK(15, 8)
 #define PCS1G_TSTPAT_STATUS_JTP_ERR_CNT_X(x)              (((x) & GENMASK(15, 8)) >> 8)
 #define PCS1G_TSTPAT_STATUS_JTP_ERR                       BIT(4)
 #define PCS1G_TSTPAT_STATUS_JTP_LOCK                      BIT(0)
 
-#define DEV_PCS_FX100_CFG                                 0x94
-
 #define DEV_PCS_FX100_CFG_SD_SEL                          BIT(26)
 #define DEV_PCS_FX100_CFG_SD_POL                          BIT(25)
 #define DEV_PCS_FX100_CFG_SD_ENA                          BIT(24)
@@ -259,8 +183,6 @@
 #define DEV_PCS_FX100_CFG_FEFGEN_ENA                      BIT(1)
 #define DEV_PCS_FX100_CFG_PCS_ENA                         BIT(0)
 
-#define DEV_PCS_FX100_STATUS                              0x98
-
 #define DEV_PCS_FX100_STATUS_EDGE_POS_PTP(x)              (((x) << 8) & GENMASK(11, 8))
 #define DEV_PCS_FX100_STATUS_EDGE_POS_PTP_M               GENMASK(11, 8)
 #define DEV_PCS_FX100_STATUS_EDGE_POS_PTP_X(x)            (((x) & GENMASK(11, 8)) >> 8)
-- 
2.25.1


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

* [PATCH net-next 04/11] soc/mscc: ocelot: add MII registers description
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (2 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 03/11] net: mscc: ocelot: convert port registers to regmap Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 05/11] net: mscc: ocelot: convert QSYS_SWITCH_PORT_MODE and SYS_PORT_MODE to regfields Vladimir Oltean
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Maxim Kochetkov <fido_max@inbox.ru>

Add the register definitions for the MSCC MIIM MDIO controller in
preparation for seville_vsc9959.c to create its accessors for the
internal MDIO bus.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/soc/mscc/ocelot.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 79c77aab87e5..85b16f099c8f 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -394,6 +394,9 @@ enum ocelot_reg {
 	PTP_CLK_CFG_ADJ_CFG,
 	PTP_CLK_CFG_ADJ_FREQ,
 	GCB_SOFT_RST = GCB << TARGET_OFFSET,
+	GCB_MIIM_MII_STATUS,
+	GCB_MIIM_MII_CMD,
+	GCB_MIIM_MII_DATA,
 	DEV_CLOCK_CFG = DEV_GMII << TARGET_OFFSET,
 	DEV_PORT_MISC,
 	DEV_EVENTS,
@@ -481,6 +484,8 @@ enum ocelot_regfield {
 	SYS_RESET_CFG_MEM_ENA,
 	SYS_RESET_CFG_MEM_INIT,
 	GCB_SOFT_RST_SWC_RST,
+	GCB_MIIM_MII_STATUS_PENDING,
+	GCB_MIIM_MII_STATUS_BUSY,
 	REGFIELD_MAX
 };
 
-- 
2.25.1


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

* [PATCH net-next 05/11] net: mscc: ocelot: convert QSYS_SWITCH_PORT_MODE and SYS_PORT_MODE to regfields
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (3 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 04/11] soc/mscc: ocelot: add MII registers description Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit Vladimir Oltean
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Currently Felix and Ocelot share the same bit layout in these per-port
registers, but Seville does not. So we need reg_fields for that.

Actually since these are per-port registers, we need to also specify the
number of ports, and register size per port, and use the regmap API for
multiple ports.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c          | 13 ++++----
 drivers/net/dsa/ocelot/felix_vsc9959.c  | 11 +++++++
 drivers/net/ethernet/mscc/ocelot.c      | 44 ++++++++++++-------------
 drivers/net/ethernet/mscc/ocelot.h      |  6 ----
 drivers/net/ethernet/mscc/ocelot_io.c   |  2 ++
 drivers/net/ethernet/mscc/ocelot_regs.c | 11 +++++++
 include/soc/mscc/ocelot.h               | 15 +++++++++
 include/soc/mscc/ocelot_qsys.h          | 13 --------
 include/soc/mscc/ocelot_sys.h           | 13 --------
 9 files changed, 68 insertions(+), 60 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 13722cde503e..8b15cbcb597c 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -260,8 +260,7 @@ static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
 
 	ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
-	ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
-		       QSYS_SWITCH_PORT_MODE, port);
+	ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
 }
 
 static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
@@ -287,10 +286,12 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
 			 ANA_PORT_PORT_CFG, port);
 
 	/* Core: Enable port for frame transfer */
-	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
-			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
-			 QSYS_SWITCH_PORT_MODE_PORT_ENA,
-			 QSYS_SWITCH_PORT_MODE, port);
+	ocelot_fields_write(ocelot, port,
+			    QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE, 1);
+	ocelot_fields_write(ocelot, port,
+			    QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG, 1);
+	ocelot_fields_write(ocelot, port,
+			    QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
 }
 
 static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index dda7a3a7aa6f..dc9480e82d70 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -503,6 +503,17 @@ static const struct reg_field vsc9959_regfields[] = {
 	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10),
 	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 0, 0),
 	[GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0),
+	/* Replicated per number of ports (7), register size 4 per port */
+	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 7, 4),
+	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 7, 4),
+	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 7, 4),
+	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 7, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 7, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 7, 4),
+	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 7, 4),
+	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 7, 4),
+	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4),
+	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 7, 4),
 };
 
 static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index d5bfa6d3e73c..0f016f497972 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -476,10 +476,12 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port,
 			 ANA_PFC_PFC_CFG, port);
 
 	/* Core: Enable port for frame transfer */
-	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
-			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
-			 QSYS_SWITCH_PORT_MODE_PORT_ENA,
-			 QSYS_SWITCH_PORT_MODE, port);
+	ocelot_fields_write(ocelot, port,
+			    QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE, 1);
+	ocelot_fields_write(ocelot, port,
+			    QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG, 1);
+	ocelot_fields_write(ocelot, port,
+			    QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
 
 	/* Flow control */
 	ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
@@ -553,8 +555,7 @@ void ocelot_port_disable(struct ocelot *ocelot, int port)
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
 
 	ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
-	ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
-		       QSYS_SWITCH_PORT_MODE, port);
+	ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
 }
 EXPORT_SYMBOL(ocelot_port_disable);
 
@@ -2185,27 +2186,26 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 			     QSYS_EXT_CPU_CFG);
 
 		/* Enable NPI port */
-		ocelot_write_rix(ocelot,
-				 QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
-				 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
-				 QSYS_SWITCH_PORT_MODE_PORT_ENA,
-				 QSYS_SWITCH_PORT_MODE, npi);
+		ocelot_fields_write(ocelot, npi,
+				    QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE, 1);
+		ocelot_fields_write(ocelot, npi,
+				    QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
 		/* NPI port Injection/Extraction configuration */
-		ocelot_write_rix(ocelot,
-				 SYS_PORT_MODE_INCL_XTR_HDR(extraction) |
-				 SYS_PORT_MODE_INCL_INJ_HDR(injection),
-				 SYS_PORT_MODE, npi);
+		ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_XTR_HDR,
+				    extraction);
+		ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_INJ_HDR,
+				    injection);
 	}
 
 	/* Enable CPU port module */
-	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
-			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
-			 QSYS_SWITCH_PORT_MODE_PORT_ENA,
-			 QSYS_SWITCH_PORT_MODE, cpu);
+	ocelot_fields_write(ocelot, cpu,
+			    QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE, 1);
+	ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
 	/* CPU port Injection/Extraction configuration */
-	ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(extraction) |
-			 SYS_PORT_MODE_INCL_INJ_HDR(injection),
-			 SYS_PORT_MODE, cpu);
+	ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
+			    extraction);
+	ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
+			    injection);
 
 	/* Configure the CPU port to be VLAN aware */
 	ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index b22997dd098e..d6a3cb5a4b36 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -63,9 +63,6 @@ struct ocelot_port_private {
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg);
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
 
-#define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val))
-#define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
-
 int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops);
 int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
 		      struct phy_device *phy);
@@ -78,7 +75,4 @@ extern struct notifier_block ocelot_netdevice_nb;
 extern struct notifier_block ocelot_switchdev_nb;
 extern struct notifier_block ocelot_switchdev_blocking_nb;
 
-#define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val))
-#define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
-
 #endif
diff --git a/drivers/net/ethernet/mscc/ocelot_io.c b/drivers/net/ethernet/mscc/ocelot_io.c
index 741f653bc85b..d22711282183 100644
--- a/drivers/net/ethernet/mscc/ocelot_io.c
+++ b/drivers/net/ethernet/mscc/ocelot_io.c
@@ -89,6 +89,8 @@ int ocelot_regfields_init(struct ocelot *ocelot,
 		regfield.reg = ocelot->map[target][reg & REG_MASK];
 		regfield.lsb = regfields[i].lsb;
 		regfield.msb = regfields[i].msb;
+		regfield.id_size = regfields[i].id_size;
+		regfield.id_offset = regfields[i].id_offset;
 
 		ocelot->regfields[i] =
 		devm_regmap_field_alloc(ocelot->dev,
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index 18d73b4e5cb5..56bdb1bb2f36 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -341,6 +341,17 @@ static const struct reg_field ocelot_regfields[] = {
 	[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 (11), register size 4 per port */
+	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 11, 4),
+	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 11, 4),
+	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 11, 4),
+	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 11, 4),
+	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 11, 4),
 };
 
 static const struct ocelot_stat_layout ocelot_stats_layout[] = {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 85b16f099c8f..8e6c13d99ced 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -475,11 +475,21 @@ enum ocelot_regfield {
 	ANA_TABLES_MACACCESS_B_DOM,
 	ANA_TABLES_MACTINDX_BUCKET,
 	ANA_TABLES_MACTINDX_M_INDEX,
+	QSYS_SWITCH_PORT_MODE_PORT_ENA,
+	QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG,
+	QSYS_SWITCH_PORT_MODE_YEL_RSRVD,
+	QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE,
+	QSYS_SWITCH_PORT_MODE_TX_PFC_ENA,
+	QSYS_SWITCH_PORT_MODE_TX_PFC_MODE,
 	QSYS_TIMED_FRAME_ENTRY_TFRM_VLD,
 	QSYS_TIMED_FRAME_ENTRY_TFRM_FP,
 	QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO,
 	QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL,
 	QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T,
+	SYS_PORT_MODE_DATA_WO_TS,
+	SYS_PORT_MODE_INCL_INJ_HDR,
+	SYS_PORT_MODE_INCL_XTR_HDR,
+	SYS_PORT_MODE_INCL_HDR_ERR,
 	SYS_RESET_CFG_CORE_ENA,
 	SYS_RESET_CFG_MEM_ENA,
 	SYS_RESET_CFG_MEM_INIT,
@@ -623,6 +633,11 @@ struct ocelot_policer {
 #define ocelot_rmw_rix(ocelot, val, m, reg, ri) __ocelot_rmw_ix(ocelot, val, m, reg, reg##_RSZ * (ri))
 #define ocelot_rmw(ocelot, val, m, reg) __ocelot_rmw_ix(ocelot, val, m, reg, 0)
 
+#define ocelot_field_write(ocelot, reg, val) regmap_field_write((ocelot)->regfields[(reg)], (val))
+#define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
+#define ocelot_fields_write(ocelot, id, reg, val) regmap_fields_write((ocelot)->regfields[(reg)], (id), (val))
+#define ocelot_fields_read(ocelot, id, reg, val) regmap_fields_read((ocelot)->regfields[(reg)], (id), (val))
+
 /* I/O */
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg);
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
diff --git a/include/soc/mscc/ocelot_qsys.h b/include/soc/mscc/ocelot_qsys.h
index d8c63aa761be..a814bc2017d8 100644
--- a/include/soc/mscc/ocelot_qsys.h
+++ b/include/soc/mscc/ocelot_qsys.h
@@ -13,19 +13,6 @@
 #define QSYS_PORT_MODE_DEQUEUE_DIS                        BIT(1)
 #define QSYS_PORT_MODE_DEQUEUE_LATE                       BIT(0)
 
-#define QSYS_SWITCH_PORT_MODE_RSZ                         0x4
-
-#define QSYS_SWITCH_PORT_MODE_PORT_ENA                    BIT(14)
-#define QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(x)             (((x) << 11) & GENMASK(13, 11))
-#define QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG_M              GENMASK(13, 11)
-#define QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG_X(x)           (((x) & GENMASK(13, 11)) >> 11)
-#define QSYS_SWITCH_PORT_MODE_YEL_RSRVD                   BIT(10)
-#define QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE           BIT(9)
-#define QSYS_SWITCH_PORT_MODE_TX_PFC_ENA(x)               (((x) << 1) & GENMASK(8, 1))
-#define QSYS_SWITCH_PORT_MODE_TX_PFC_ENA_M                GENMASK(8, 1)
-#define QSYS_SWITCH_PORT_MODE_TX_PFC_ENA_X(x)             (((x) & GENMASK(8, 1)) >> 1)
-#define QSYS_SWITCH_PORT_MODE_TX_PFC_MODE                 BIT(0)
-
 #define QSYS_STAT_CNT_CFG_TX_GREEN_CNT_MODE               BIT(5)
 #define QSYS_STAT_CNT_CFG_TX_YELLOW_CNT_MODE              BIT(4)
 #define QSYS_STAT_CNT_CFG_DROP_GREEN_CNT_MODE             BIT(3)
diff --git a/include/soc/mscc/ocelot_sys.h b/include/soc/mscc/ocelot_sys.h
index 16f91e172bcb..8a95fc93fde5 100644
--- a/include/soc/mscc/ocelot_sys.h
+++ b/include/soc/mscc/ocelot_sys.h
@@ -12,19 +12,6 @@
 
 #define SYS_COUNT_TX_OCTETS_RSZ                           0x4
 
-#define SYS_PORT_MODE_RSZ                                 0x4
-
-#define SYS_PORT_MODE_DATA_WO_TS(x)                       (((x) << 5) & GENMASK(6, 5))
-#define SYS_PORT_MODE_DATA_WO_TS_M                        GENMASK(6, 5)
-#define SYS_PORT_MODE_DATA_WO_TS_X(x)                     (((x) & GENMASK(6, 5)) >> 5)
-#define SYS_PORT_MODE_INCL_INJ_HDR(x)                     (((x) << 3) & GENMASK(4, 3))
-#define SYS_PORT_MODE_INCL_INJ_HDR_M                      GENMASK(4, 3)
-#define SYS_PORT_MODE_INCL_INJ_HDR_X(x)                   (((x) & GENMASK(4, 3)) >> 3)
-#define SYS_PORT_MODE_INCL_XTR_HDR(x)                     (((x) << 1) & GENMASK(2, 1))
-#define SYS_PORT_MODE_INCL_XTR_HDR_M                      GENMASK(2, 1)
-#define SYS_PORT_MODE_INCL_XTR_HDR_X(x)                   (((x) & GENMASK(2, 1)) >> 1)
-#define SYS_PORT_MODE_INJ_HDR_ERR                         BIT(0)
-
 #define SYS_FRONT_PORT_MODE_RSZ                           0x4
 
 #define SYS_FRONT_PORT_MODE_HDX_MODE                      BIT(0)
-- 
2.25.1


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

* [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (4 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 05/11] net: mscc: ocelot: convert QSYS_SWITCH_PORT_MODE and SYS_PORT_MODE to regfields Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-28 14:50   ` Andrew Lunn
  2020-05-27 23:41 ` [PATCH net-next 07/11] net: mscc: ocelot: split writes to pause frame enable bit and to thresholds Vladimir Oltean
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

With this patch we try to kill 2 birds with 1 stone.

First of all, some switches that use tag_ocelot.c don't have the exact
same bitfield layout for the DSA tags. The destination ports field is
different for Seville VSC9953 for example. So the choices are to either
duplicate tag_ocelot.c into a new tag_seville.c (sub-optimal) or somehow
take into account a supposed ocelot->dest_ports_offset when packing this
field into the DSA injection header (again not ideal).

Secondly, tag_ocelot.c already needs to memset a 128-bit area to zero
and call some packing() functions of dubious performance in the
fastpath. And most of the values it needs to pack are pretty much
constant (BYPASS=1, SRC_PORT=CPU, DEST=port index). So it would be good
if we could improve that.

The proposed solution is to allocate a memory area per port at probe
time, initialize that with the statically defined bits as per chip
hardware revision, and just perform a simpler memcpy in the fastpath.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c | 23 +++++++++++++++++++++++
 include/soc/mscc/ocelot.h      |  2 ++
 net/dsa/tag_ocelot.c           | 21 ++++++++-------------
 3 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 8b15cbcb597c..0a392e0f4fbb 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -480,6 +480,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 	for (port = 0; port < num_phys_ports; port++) {
 		struct ocelot_port *ocelot_port;
 		struct regmap *target;
+		u64 bypass, dest, src;
+		u8 *template;
 
 		ocelot_port = devm_kzalloc(ocelot->dev,
 					   sizeof(struct ocelot_port),
@@ -505,9 +507,30 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 			return PTR_ERR(target);
 		}
 
+		template = devm_kzalloc(ocelot->dev, OCELOT_TAG_LEN,
+					GFP_KERNEL);
+		if (!template) {
+			dev_err(ocelot->dev,
+				"Failed to allocate memory for DSA tag\n");
+			kfree(port_phy_modes);
+			return -ENOMEM;
+		}
+
+		/* Set the source port as the CPU port module and not the
+		 * NPI port
+		 */
+		src = ocelot->num_phys_ports;
+		dest = BIT(port);
+		bypass = true;
+
+		packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
+		packing(template, &dest,    68,  56, OCELOT_TAG_LEN, PACK, 0);
+		packing(template, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
+
 		ocelot_port->phy_mode = port_phy_modes[port];
 		ocelot_port->ocelot = ocelot;
 		ocelot_port->target = target;
+		ocelot_port->xmit_template = template;
 		ocelot->ports[port] = ocelot_port;
 	}
 
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 8e6c13d99ced..1a87a3a32616 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -549,6 +549,8 @@ struct ocelot_port {
 	u8				ts_id;
 
 	phy_interface_t			phy_mode;
+
+	u8				*xmit_template;
 };
 
 struct ocelot {
diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c
index b0c98ee4e13b..42f327c06dca 100644
--- a/net/dsa/tag_ocelot.c
+++ b/net/dsa/tag_ocelot.c
@@ -137,11 +137,10 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
 				   struct net_device *netdev)
 {
 	struct dsa_port *dp = dsa_slave_to_port(netdev);
-	u64 bypass, dest, src, qos_class, rew_op;
 	struct dsa_switch *ds = dp->ds;
-	int port = dp->index;
 	struct ocelot *ocelot = ds->priv;
-	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	struct ocelot_port *ocelot_port;
+	u64 qos_class, rew_op;
 	u8 *injection;
 
 	if (unlikely(skb_cow_head(skb, OCELOT_TAG_LEN) < 0)) {
@@ -149,19 +148,15 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
 		return NULL;
 	}
 
-	injection = skb_push(skb, OCELOT_TAG_LEN);
+	ocelot_port = ocelot->ports[dp->index];
 
-	memset(injection, 0, OCELOT_TAG_LEN);
+	injection = skb_push(skb, OCELOT_TAG_LEN);
 
-	/* Set the source port as the CPU port module and not the NPI port */
-	src = ocelot->num_phys_ports;
-	dest = BIT(port);
-	bypass = true;
+	memcpy(injection, ocelot_port->xmit_template, OCELOT_TAG_LEN);
+	/* Fix up the fields which are not statically determined
+	 * in the template
+	 */
 	qos_class = skb->priority;
-
-	packing(injection, &bypass,   127, 127, OCELOT_TAG_LEN, PACK, 0);
-	packing(injection, &dest,      68,  56, OCELOT_TAG_LEN, PACK, 0);
-	packing(injection, &src,       46,  43, OCELOT_TAG_LEN, PACK, 0);
 	packing(injection, &qos_class, 19,  17, OCELOT_TAG_LEN, PACK, 0);
 
 	if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
-- 
2.25.1


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

* [PATCH net-next 07/11] net: mscc: ocelot: split writes to pause frame enable bit and to thresholds
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (5 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 08/11] net: mscc: ocelot: disable flow control on NPI interface Vladimir Oltean
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

We don't want ocelot_port_set_maxlen to enable pause frame TX, just to
adjust the pause thresholds.

Move the unconditional enabling of pause TX to ocelot_init_port. There
is no good place to put such setting because it shouldn't be
unconditional. But at the moment it is, we're not changing that.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 0f016f497972..6fc5b72c9260 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2012,6 +2012,7 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
 {
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
 	int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
+	int pause_start, pause_stop;
 	int atop_wm;
 
 	if (port == ocelot->npi) {
@@ -2025,13 +2026,13 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
 
 	ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);
 
-	/* Set Pause WM hysteresis
-	 * 152 = 6 * maxlen / OCELOT_BUFFER_CELL_SZ
-	 * 101 = 4 * maxlen / OCELOT_BUFFER_CELL_SZ
-	 */
-	ocelot_write_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA |
-			 SYS_PAUSE_CFG_PAUSE_STOP(101) |
-			 SYS_PAUSE_CFG_PAUSE_START(152), SYS_PAUSE_CFG, port);
+	/* Set Pause watermark hysteresis */
+	pause_start = 6 * maxlen / OCELOT_BUFFER_CELL_SZ;
+	pause_stop = 4 * maxlen / OCELOT_BUFFER_CELL_SZ;
+	ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_START(pause_start),
+		       SYS_PAUSE_CFG_PAUSE_START_M, SYS_PAUSE_CFG, port);
+	ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_STOP(pause_stop),
+		       SYS_PAUSE_CFG_PAUSE_STOP_M, SYS_PAUSE_CFG, port);
 
 	/* Tail dropping watermark */
 	atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
@@ -2094,6 +2095,10 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
 	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_HIGH_CFG);
 	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG);
 
+	/* Enable transmission of pause frames */
+	ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA, SYS_PAUSE_CFG_PAUSE_ENA,
+		       SYS_PAUSE_CFG, port);
+
 	/* Drop frames with multicast source address */
 	ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
 		       ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
-- 
2.25.1


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

* [PATCH net-next 08/11] net: mscc: ocelot: disable flow control on NPI interface
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (6 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 07/11] net: mscc: ocelot: split writes to pause frame enable bit and to thresholds Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 09/11] net: mscc: ocelot: convert SYS_PAUSE_CFG register access to regfield Vladimir Oltean
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The Ocelot switches do not support flow control on Ethernet interfaces
where a DSA tag must be added. If pause frames are enabled, they will be
encapsulated in the DSA tag just like regular frames, and the DSA master
will not recognize them.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 6fc5b72c9260..41d1026ec5b3 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2200,6 +2200,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 				    extraction);
 		ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_INJ_HDR,
 				    injection);
+
+		/* Disable transmission of pause frames */
+		ocelot_rmw_rix(ocelot, 0, SYS_PAUSE_CFG_PAUSE_ENA,
+			       SYS_PAUSE_CFG, npi);
 	}
 
 	/* Enable CPU port module */
-- 
2.25.1


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

* [PATCH net-next 09/11] net: mscc: ocelot: convert SYS_PAUSE_CFG register access to regfield
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (7 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 08/11] net: mscc: ocelot: disable flow control on NPI interface Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 10/11] net: mscc: ocelot: extend watermark encoding function Vladimir Oltean
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Maxim Kochetkov <fido_max@inbox.ru>

Seville has a different bitwise layout than Ocelot and Felix.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c  |  3 +++
 drivers/net/ethernet/mscc/ocelot.c      | 14 ++++++--------
 drivers/net/ethernet/mscc/ocelot_regs.c |  3 +++
 include/soc/mscc/ocelot.h               |  3 +++
 include/soc/mscc/ocelot_sys.h           | 10 ----------
 5 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index dc9480e82d70..bd0bb720558c 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -514,6 +514,9 @@ static const struct reg_field vsc9959_regfields[] = {
 	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 7, 4),
 	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4),
 	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 7, 4),
+	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 7, 4),
+	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 7, 4),
+	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4),
 };
 
 static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 41d1026ec5b3..b66589a5300c 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2029,10 +2029,10 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
 	/* Set Pause watermark hysteresis */
 	pause_start = 6 * maxlen / OCELOT_BUFFER_CELL_SZ;
 	pause_stop = 4 * maxlen / OCELOT_BUFFER_CELL_SZ;
-	ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_START(pause_start),
-		       SYS_PAUSE_CFG_PAUSE_START_M, SYS_PAUSE_CFG, port);
-	ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_STOP(pause_stop),
-		       SYS_PAUSE_CFG_PAUSE_STOP_M, SYS_PAUSE_CFG, port);
+	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_START,
+			    pause_start);
+	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_STOP,
+			    pause_stop);
 
 	/* Tail dropping watermark */
 	atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
@@ -2096,8 +2096,7 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
 	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG);
 
 	/* Enable transmission of pause frames */
-	ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA, SYS_PAUSE_CFG_PAUSE_ENA,
-		       SYS_PAUSE_CFG, port);
+	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1);
 
 	/* Drop frames with multicast source address */
 	ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
@@ -2202,8 +2201,7 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 				    injection);
 
 		/* Disable transmission of pause frames */
-		ocelot_rmw_rix(ocelot, 0, SYS_PAUSE_CFG_PAUSE_ENA,
-			       SYS_PAUSE_CFG, npi);
+		ocelot_fields_write(ocelot, npi, SYS_PAUSE_CFG_PAUSE_ENA, 0);
 	}
 
 	/* Enable CPU port module */
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index 56bdb1bb2f36..eeb4771a9a2a 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -352,6 +352,9 @@ static const struct reg_field ocelot_regfields[] = {
 	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 11, 4),
 	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 11, 4),
 	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 11, 4),
+	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 11, 4),
+	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 11, 4),
+	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 11, 4),
 };
 
 static const struct ocelot_stat_layout ocelot_stats_layout[] = {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 1a87a3a32616..a97cc1796b5e 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -496,6 +496,9 @@ enum ocelot_regfield {
 	GCB_SOFT_RST_SWC_RST,
 	GCB_MIIM_MII_STATUS_PENDING,
 	GCB_MIIM_MII_STATUS_BUSY,
+	SYS_PAUSE_CFG_PAUSE_START,
+	SYS_PAUSE_CFG_PAUSE_STOP,
+	SYS_PAUSE_CFG_PAUSE_ENA,
 	REGFIELD_MAX
 };
 
diff --git a/include/soc/mscc/ocelot_sys.h b/include/soc/mscc/ocelot_sys.h
index 8a95fc93fde5..79cf40ccdbe6 100644
--- a/include/soc/mscc/ocelot_sys.h
+++ b/include/soc/mscc/ocelot_sys.h
@@ -43,16 +43,6 @@
 #define SYS_TIMESTAMP_OFFSET_TIMESTAMP_OFFSET(x)          ((x) & GENMASK(5, 0))
 #define SYS_TIMESTAMP_OFFSET_TIMESTAMP_OFFSET_M           GENMASK(5, 0)
 
-#define SYS_PAUSE_CFG_RSZ                                 0x4
-
-#define SYS_PAUSE_CFG_PAUSE_START(x)                      (((x) << 10) & GENMASK(18, 10))
-#define SYS_PAUSE_CFG_PAUSE_START_M                       GENMASK(18, 10)
-#define SYS_PAUSE_CFG_PAUSE_START_X(x)                    (((x) & GENMASK(18, 10)) >> 10)
-#define SYS_PAUSE_CFG_PAUSE_STOP(x)                       (((x) << 1) & GENMASK(9, 1))
-#define SYS_PAUSE_CFG_PAUSE_STOP_M                        GENMASK(9, 1)
-#define SYS_PAUSE_CFG_PAUSE_STOP_X(x)                     (((x) & GENMASK(9, 1)) >> 1)
-#define SYS_PAUSE_CFG_PAUSE_ENA                           BIT(0)
-
 #define SYS_PAUSE_TOT_CFG_PAUSE_TOT_START(x)              (((x) << 9) & GENMASK(17, 9))
 #define SYS_PAUSE_TOT_CFG_PAUSE_TOT_START_M               GENMASK(17, 9)
 #define SYS_PAUSE_TOT_CFG_PAUSE_TOT_START_X(x)            (((x) & GENMASK(17, 9)) >> 9)
-- 
2.25.1


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

* [PATCH net-next 10/11] net: mscc: ocelot: extend watermark encoding function
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (8 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 09/11] net: mscc: ocelot: convert SYS_PAUSE_CFG register access to regfield Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-27 23:41 ` [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch Vladimir Oltean
  2020-05-29 16:51 ` [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Mark Brown
  11 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Maxim Kochetkov <fido_max@inbox.ru>

The ocelot_wm_encode function deals with setting thresholds for pause
frame start and stop. In Ocelot and Felix the register layout is the
same, but for Seville, it isn't. The easiest way to accommodate Seville
hardware configuration is to introduce a function pointer for setting
this up.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c   | 13 +++++++++++++
 drivers/net/ethernet/mscc/ocelot.c       | 16 ++--------------
 drivers/net/ethernet/mscc/ocelot_board.c | 13 +++++++++++++
 include/soc/mscc/ocelot.h                |  1 +
 4 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index bd0bb720558c..8efcc2bda2b0 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1162,8 +1162,21 @@ static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port,
 	}
 }
 
+/* Watermark encode
+ * Bit 8:   Unit; 0:1, 1:16
+ * Bit 7-0: Value to be multiplied with unit
+ */
+static u16 vsc9959_wm_enc(u16 value)
+{
+	if (value >= BIT(8))
+		return BIT(8) | (value / 16);
+
+	return value;
+}
+
 static const struct ocelot_ops vsc9959_ops = {
 	.reset			= vsc9959_reset,
+	.wm_enc			= vsc9959_wm_enc,
 };
 
 static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index b66589a5300c..583f62c52131 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -396,18 +396,6 @@ static void ocelot_vlan_init(struct ocelot *ocelot)
 	}
 }
 
-/* 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)
-{
-	if (value >= BIT(8))
-		return BIT(8) | (value / 16);
-
-	return value;
-}
-
 void ocelot_adjust_link(struct ocelot *ocelot, int port,
 			struct phy_device *phydev)
 {
@@ -2037,9 +2025,9 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
 	/* Tail dropping watermark */
 	atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
 		   OCELOT_BUFFER_CELL_SZ;
-	ocelot_write_rix(ocelot, ocelot_wm_enc(9 * maxlen),
+	ocelot_write_rix(ocelot, ocelot->ops->wm_enc(9 * maxlen),
 			 SYS_ATOP, port);
-	ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
+	ocelot_write(ocelot, ocelot->ops->wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
 }
 EXPORT_SYMBOL(ocelot_port_set_maxlen);
 
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index b6ea9694c3ae..4a807a9027f5 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -239,8 +239,21 @@ 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)
+{
+	if (value >= BIT(8))
+		return BIT(8) | (value / 16);
+
+	return value;
+}
+
 static const struct ocelot_ops ocelot_ops = {
 	.reset			= ocelot_reset,
+	.wm_enc			= ocelot_wm_enc,
 };
 
 static const struct vcap_field vsc7514_vcap_is2_keys[] = {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index a97cc1796b5e..8a2cb5ea17e7 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -526,6 +526,7 @@ struct ocelot;
 
 struct ocelot_ops {
 	int (*reset)(struct ocelot *ocelot);
+	u16 (*wm_enc)(u16 value);
 };
 
 struct ocelot_acl_block {
-- 
2.25.1


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

* [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (9 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 10/11] net: mscc: ocelot: extend watermark encoding function Vladimir Oltean
@ 2020-05-27 23:41 ` Vladimir Oltean
  2020-05-28 16:21   ` Jakub Kicinski
  2020-05-28 21:56   ` Andrew Lunn
  2020-05-29 16:51 ` [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Mark Brown
  11 siblings, 2 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:41 UTC (permalink / raw)
  To: davem
  Cc: netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

From: Maxim Kochetkov <fido_max@inbox.ru>

This is a 10-port (8 external, 2 internal) switch from
Vitesse/Microsemi/Microchip that is integrated into the Freescale/NXP
T1040 PowerPC SoC. The situation is very similar to Felix from NXP
LS1028A, except that this is a platform device and Felix is a PCI
device.

Extending the Felix driver to probe a PCI as well as a platform device
would have introduced unnecessary complexity. The 'meat' of both drivers
is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
duplicate the Felix driver, s/Felix/Seville/, and define the low-level
bits in seville_vsc9953.c.

Like Felix, this driver configures its own PCS on the internal MDIO bus
using a phy_device abstraction for it (yes, it will be refactored to use
a raw mdio_device, like other phylink drivers do, but let's keep it like
that for now). But unlike Felix, the MDIO bus and the PCS are not from
the same vendor. The PCS is the same QorIQ/Layerscape PCS as found in
Felix/ENETC/DPAA*, but the internal MDIO bus that is used to access it
is actually an instantiation of drivers/net/phy/mdio-mscc-miim.c. But it
would be difficult to reuse that driver (it doesn't even use regmap, and
it's less than 200 lines of code), so we hand-roll here some internal
MDIO bus accessors within seville_vsc9953.c, which serves the purpose of
driving the PCS absolutely fine.

Also, same as Felix, the PCS doesn't support dynamic reconfiguration of
SerDes protocol, so we need to do pre-validation of PHY mode from device
tree and not let phylink change it.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/Kconfig           |   12 +
 drivers/net/dsa/ocelot/Makefile          |    6 +
 drivers/net/dsa/ocelot/seville.c         |  742 +++++++++++++++
 drivers/net/dsa/ocelot/seville.h         |   50 +
 drivers/net/dsa/ocelot/seville_vsc9953.c | 1064 ++++++++++++++++++++++
 5 files changed, 1874 insertions(+)
 create mode 100644 drivers/net/dsa/ocelot/seville.c
 create mode 100644 drivers/net/dsa/ocelot/seville.h
 create mode 100644 drivers/net/dsa/ocelot/seville_vsc9953.c

diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index a5b7cca03d09..38763b829b17 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig
@@ -12,3 +12,15 @@ config NET_DSA_MSCC_FELIX
 	  the Vitesse / Microsemi / Microchip Ocelot family of switching cores.
 	  It is embedded as a PCIe function of the NXP LS1028A ENETC integrated
 	  endpoint.
+
+config NET_DSA_MSCC_SEVILLE
+	tristate "Ocelot / Seville Ethernet switch support"
+	depends on NET_DSA
+	depends on NET_VENDOR_MICROSEMI
+	depends on NET_VENDOR_FREESCALE
+	select MSCC_OCELOT_SWITCH
+	select NET_DSA_TAG_OCELOT
+	help
+	  This driver supports the VSC9953 network switch, which is a member of
+	  the Vitesse / Microsemi / Microchip Ocelot family of switching cores.
+	  It is embedded inside the NXP T1040 SoC.
diff --git a/drivers/net/dsa/ocelot/Makefile b/drivers/net/dsa/ocelot/Makefile
index 37ad403e0b2a..17b1ccdcbf17 100644
--- a/drivers/net/dsa/ocelot/Makefile
+++ b/drivers/net/dsa/ocelot/Makefile
@@ -4,3 +4,9 @@ obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
 mscc_felix-objs := \
 	felix.o \
 	felix_vsc9959.o
+
+obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o
+
+mscc_seville-objs := \
+	seville.o \
+	seville_vsc9953.o
diff --git a/drivers/net/dsa/ocelot/seville.c b/drivers/net/dsa/ocelot/seville.c
new file mode 100644
index 000000000000..bc9c62d2d994
--- /dev/null
+++ b/drivers/net/dsa/ocelot/seville.c
@@ -0,0 +1,742 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Distributed Switch Architecture VSC9953 driver
+ * Copyright (C) 2020, Maxim Kochetkov <fido_max@inbox.ru>
+ */
+#include <uapi/linux/if_bridge.h>
+#include <soc/mscc/ocelot_qsys.h>
+#include <soc/mscc/ocelot_sys.h>
+#include <soc/mscc/ocelot_dev.h>
+#include <soc/mscc/ocelot_ana.h>
+#include <soc/mscc/ocelot.h>
+#include <linux/packing.h>
+#include <linux/module.h>
+#include <linux/of_net.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <net/pkt_sched.h>
+#include <net/dsa.h>
+#include "seville.h"
+
+static enum dsa_tag_protocol seville_get_tag_protocol(struct dsa_switch *ds,
+						      int port,
+						      enum dsa_tag_protocol mp)
+{
+	return DSA_TAG_PROTO_OCELOT;
+}
+
+static int seville_set_ageing_time(struct dsa_switch *ds,
+				   unsigned int ageing_time)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_set_ageing_time(ocelot, ageing_time);
+
+	return 0;
+}
+
+static int seville_fdb_dump(struct dsa_switch *ds, int port,
+			    dsa_fdb_dump_cb_t *cb, void *data)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_fdb_dump(ocelot, port, cb, data);
+}
+
+static int seville_fdb_add(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_fdb_add(ocelot, port, addr, vid);
+}
+
+static int seville_fdb_del(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_fdb_del(ocelot, port, addr, vid);
+}
+
+static void seville_bridge_stp_state_set(struct dsa_switch *ds, int port,
+				         u8 state)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_bridge_stp_state_set(ocelot, port, state);
+}
+
+static int seville_bridge_join(struct dsa_switch *ds, int port,
+			       struct net_device *br)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_port_bridge_join(ocelot, port, br);
+}
+
+static void seville_bridge_leave(struct dsa_switch *ds, int port,
+			         struct net_device *br)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_port_bridge_leave(ocelot, port, br);
+}
+
+/* This callback needs to be present */
+static int seville_vlan_prepare(struct dsa_switch *ds, int port,
+			        const struct switchdev_obj_port_vlan *vlan)
+{
+	return 0;
+}
+
+static int seville_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_port_vlan_filtering(ocelot, port, enabled);
+
+	return 0;
+}
+
+static void seville_vlan_add(struct dsa_switch *ds, int port,
+			     const struct switchdev_obj_port_vlan *vlan)
+{
+	struct ocelot *ocelot = ds->priv;
+	u16 flags = vlan->flags;
+	u16 vid;
+	int err;
+
+	if (dsa_is_cpu_port(ds, port))
+		flags &= ~BRIDGE_VLAN_INFO_UNTAGGED;
+
+	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
+		err = ocelot_vlan_add(ocelot, port, vid,
+				      flags & BRIDGE_VLAN_INFO_PVID,
+				      flags & BRIDGE_VLAN_INFO_UNTAGGED);
+		if (err) {
+			dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n",
+				vid, port, err);
+			return;
+		}
+	}
+}
+
+static int seville_vlan_del(struct dsa_switch *ds, int port,
+			    const struct switchdev_obj_port_vlan *vlan)
+{
+	struct ocelot *ocelot = ds->priv;
+	u16 vid;
+	int err;
+
+	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
+		err = ocelot_vlan_del(ocelot, port, vid);
+		if (err) {
+			dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n",
+				vid, port, err);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int seville_port_enable(struct dsa_switch *ds, int port,
+			       struct phy_device *phy)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_port_enable(ocelot, port, phy);
+
+	return 0;
+}
+
+static void seville_port_disable(struct dsa_switch *ds, int port)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_port_disable(ocelot, port);
+}
+
+static void seville_phylink_validate(struct dsa_switch *ds, int port,
+				     unsigned long *supported,
+				     struct phylink_link_state *state)
+{
+	struct ocelot *ocelot = ds->priv;
+	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;
+	}
+
+	/* No half-duplex. */
+	phylink_set_port_modes(mask);
+	phylink_set(mask, Autoneg);
+	phylink_set(mask, Pause);
+	phylink_set(mask, Asym_Pause);
+	phylink_set(mask, 10baseT_Full);
+	phylink_set(mask, 100baseT_Full);
+	phylink_set(mask, 1000baseT_Full);
+
+	if (state->interface == PHY_INTERFACE_MODE_INTERNAL ||
+	    state->interface == PHY_INTERFACE_MODE_2500BASEX) {
+		phylink_set(mask, 2500baseT_Full);
+		phylink_set(mask, 2500baseX_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 seville_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port,
+					     struct phylink_link_state *state)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct seville *seville = ocelot_to_seville(ocelot);
+
+	if (seville->info->pcs_link_state)
+		seville->info->pcs_link_state(ocelot, port, state);
+
+	return 0;
+}
+
+static void seville_phylink_mac_config(struct dsa_switch *ds, int port,
+				       unsigned int link_an_mode,
+				       const struct phylink_link_state *state)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	struct seville *seville = ocelot_to_seville(ocelot);
+
+	if (port == 8 || port == 9) {
+		ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(OCELOT_SPEED_2500),
+			 ANA_PFC_PFC_CFG, port);
+		/* 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_2500),
+				 SYS_MAC_FC_CFG, port);
+	} else {
+		ocelot_write_gix(ocelot,
+				 ANA_PFC_PFC_CFG_FC_LINK_SPEED(OCELOT_SPEED_1000),
+				 ANA_PFC_PFC_CFG, port);
+		/* 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, port);
+	}
+
+	ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(OCELOT_SPEED_1000),
+			   DEV_CLOCK_CFG);
+
+	/* Enable MAC module */
+	ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
+			   DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
+
+	if (seville->info->pcs_init)
+		seville->info->pcs_init(ocelot, port, link_an_mode, state);
+}
+
+static void seville_phylink_mac_an_restart(struct dsa_switch *ds, int port)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct seville *seville = ocelot_to_seville(ocelot);
+
+	if (seville->info->pcs_an_restart)
+		seville->info->pcs_an_restart(ocelot, port);
+}
+
+static void seville_phylink_mac_link_down(struct dsa_switch *ds, int port,
+					  unsigned int link_an_mode,
+					  phy_interface_t interface)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+	ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
+	ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
+}
+
+static void seville_phylink_mac_link_up(struct dsa_switch *ds, int port,
+					unsigned int link_an_mode,
+					phy_interface_t interface,
+					struct phy_device *phydev,
+					int speed, int duplex,
+					bool tx_pause, bool rx_pause)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+	/* Enable MAC module */
+	ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
+			   DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
+
+	/* Enable receiving frames on the port, and activate 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(port),
+			 ANA_PORT_PORT_CFG, port);
+
+	/* Core: Enable port for frame transfer */
+	ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE, 1);
+	ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
+}
+
+static void seville_get_strings(struct dsa_switch *ds, int port,
+				u32 stringset, u8 *data)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_get_strings(ocelot, port, stringset, data);
+}
+
+static void seville_get_ethtool_stats(struct dsa_switch *ds, int port,
+				      u64 *data)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_get_ethtool_stats(ocelot, port, data);
+}
+
+static int seville_get_sset_count(struct dsa_switch *ds, int port, int sset)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_get_sset_count(ocelot, port, sset);
+}
+
+static int seville_parse_ports_node(struct seville *seville,
+				    struct device_node *ports_node,
+				    phy_interface_t *port_phy_modes)
+{
+	struct ocelot *ocelot = &seville->ocelot;
+	struct device *dev = seville->ocelot.dev;
+	struct device_node *child;
+
+	for_each_available_child_of_node(ports_node, child) {
+		phy_interface_t phy_mode;
+		u32 port;
+		int err;
+
+		/* Get switch port number from DT */
+		if (of_property_read_u32(child, "reg", &port) < 0) {
+			dev_err(dev, "Port number not defined in device tree "
+				"(property \"reg\")\n");
+			of_node_put(child);
+			return -ENODEV;
+		}
+
+		/* Get PHY mode from DT */
+		err = of_get_phy_mode(child, &phy_mode);
+		if (err) {
+			dev_err(dev, "Failed to read phy-mode or "
+				"phy-interface-type property for port %d\n",
+				port);
+			of_node_put(child);
+			return -ENODEV;
+		}
+
+		err = seville->info->prevalidate_phy_mode(ocelot, port,
+							  phy_mode);
+		if (err < 0) {
+			dev_err(dev, "Unsupported PHY mode %s on port %d\n",
+				phy_modes(phy_mode), port);
+			return err;
+		}
+
+		port_phy_modes[port] = phy_mode;
+	}
+
+	return 0;
+}
+
+static int seville_parse_dt(struct seville *seville,
+			    phy_interface_t *port_phy_modes)
+{
+	struct device *dev = seville->ocelot.dev;
+	struct device_node *switch_node;
+	struct device_node *ports_node;
+	int err;
+
+	switch_node = dev->of_node;
+
+	ports_node = of_get_child_by_name(switch_node, "ports");
+	if (!ports_node) {
+		dev_err(dev, "Incorrect bindings: absent \"ports\" node\n");
+		return -ENODEV;
+	}
+
+	err = seville_parse_ports_node(seville, ports_node, port_phy_modes);
+	of_node_put(ports_node);
+
+	return err;
+}
+
+static int seville_init_structs(struct seville *seville, int num_phys_ports)
+{
+	struct ocelot *ocelot = &seville->ocelot;
+	phy_interface_t *port_phy_modes;
+	struct resource res;
+	int port, i, err;
+
+	ocelot->num_phys_ports = num_phys_ports;
+	ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports,
+				     sizeof(struct ocelot_port *), GFP_KERNEL);
+	if (!ocelot->ports)
+		return -ENOMEM;
+
+	ocelot->map		= seville->info->map;
+	ocelot->stats_layout	= seville->info->stats_layout;
+	ocelot->num_stats	= seville->info->num_stats;
+	ocelot->shared_queue_sz	= seville->info->shared_queue_sz;
+	ocelot->num_mact_rows	= seville->info->num_mact_rows;
+	ocelot->vcap_is2_keys	= seville->info->vcap_is2_keys;
+	ocelot->vcap_is2_actions = seville->info->vcap_is2_actions;
+	ocelot->vcap		= seville->info->vcap;
+	ocelot->ops		= seville->info->ops;
+
+	port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
+				 GFP_KERNEL);
+	if (!port_phy_modes)
+		return -ENOMEM;
+
+	err = seville_parse_dt(seville, port_phy_modes);
+	if (err) {
+		kfree(port_phy_modes);
+		return err;
+	}
+
+	for (i = 0; i < TARGET_MAX; i++) {
+		struct regmap *target;
+
+		if (!seville->info->target_io_res[i].name)
+			continue;
+
+		memcpy(&res, &seville->info->target_io_res[i], sizeof(res));
+		res.flags = IORESOURCE_MEM;
+		res.start += seville->switch_base;
+		res.end += seville->switch_base;
+
+		target = ocelot_regmap_init(ocelot, &res);
+		if (IS_ERR(target)) {
+			dev_err(ocelot->dev,
+				"Failed to map device memory space\n");
+			kfree(port_phy_modes);
+			return PTR_ERR(target);
+		}
+
+		ocelot->targets[i] = target;
+	}
+
+	err = ocelot_regfields_init(ocelot, seville->info->regfields);
+	if (err) {
+		dev_err(ocelot->dev, "failed to init reg fields map\n");
+		kfree(port_phy_modes);
+		return err;
+	}
+
+	for (port = 0; port < num_phys_ports; port++) {
+		struct ocelot_port *ocelot_port;
+		struct regmap *target;
+		u64 bypass, dest, src;
+		u8 *template;
+
+		ocelot_port = devm_kzalloc(ocelot->dev,
+					   sizeof(struct ocelot_port),
+					   GFP_KERNEL);
+		if (!ocelot_port) {
+			dev_err(ocelot->dev,
+				"failed to allocate port memory\n");
+			kfree(port_phy_modes);
+			return -ENOMEM;
+		}
+
+		memcpy(&res, &seville->info->port_io_res[port], sizeof(res));
+		res.flags = IORESOURCE_MEM;
+		res.start += seville->switch_base;
+		res.end += seville->switch_base;
+
+		target = ocelot_regmap_init(ocelot, &res);
+		if (IS_ERR(target)) {
+			dev_err(ocelot->dev,
+				"Failed to map memory space for port %d\n",
+				port);
+			kfree(port_phy_modes);
+			return PTR_ERR(target);
+		}
+
+		template = devm_kzalloc(ocelot->dev, OCELOT_TAG_LEN,
+					GFP_KERNEL);
+		if (!template) {
+			dev_err(ocelot->dev,
+				"Failed to allocate memory for DSA tag\n");
+			kfree(port_phy_modes);
+			return -ENOMEM;
+		}
+
+		/* Set the source port as the CPU port module and not the
+		 * NPI port
+		 */
+		src = ocelot->num_phys_ports;
+		dest = BIT(port);
+		bypass = true;
+
+		packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
+		packing(template, &dest,    67,  57, OCELOT_TAG_LEN, PACK, 0);
+		packing(template, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
+
+		ocelot_port->phy_mode = port_phy_modes[port];
+		ocelot_port->ocelot = ocelot;
+		ocelot_port->target = target;
+		ocelot_port->xmit_template = template;
+		ocelot->ports[port] = ocelot_port;
+	}
+
+	kfree(port_phy_modes);
+
+	if (seville->info->mdio_bus_alloc) {
+		err = seville->info->mdio_bus_alloc(ocelot);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int seville_setup(struct dsa_switch *ds)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct seville *seville = ocelot_to_seville(ocelot);
+	int port, err;
+
+	err = seville_init_structs(seville, ds->num_ports);
+	if (err)
+		return err;
+
+	ocelot_init(ocelot);
+
+	for (port = 0; port < ds->num_ports; port++) {
+		ocelot_init_port(ocelot, port);
+		if (dsa_is_cpu_port(ds, port))
+			ocelot_configure_cpu(ocelot, port,
+					     OCELOT_TAG_PREFIX_NONE,
+					     OCELOT_TAG_PREFIX_LONG);
+	}
+
+	ocelot_write_rix(ocelot,
+			 ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)),
+			 ANA_PGID_PGID, PGID_UC);
+
+	ds->mtu_enforcement_ingress = true;
+	ds->configure_vlan_while_not_filtering = true;
+	return 0;
+}
+
+static void seville_teardown(struct dsa_switch *ds)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct seville *seville = ocelot_to_seville(ocelot);
+
+	if (seville->info->mdio_bus_free)
+		seville->info->mdio_bus_free(ocelot);
+
+	/* stop workqueue thread */
+	ocelot_deinit(ocelot);
+}
+
+static int seville_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_port_set_maxlen(ocelot, port, new_mtu);
+
+	return 0;
+}
+
+static int seville_get_max_mtu(struct dsa_switch *ds, int port)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_get_max_mtu(ocelot, port);
+}
+
+static int seville_cls_flower_add(struct dsa_switch *ds, int port,
+				struct flow_cls_offload *cls, bool ingress)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_cls_flower_replace(ocelot, port, cls, ingress);
+}
+
+static int seville_cls_flower_del(struct dsa_switch *ds, int port,
+				struct flow_cls_offload *cls, bool ingress)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_cls_flower_destroy(ocelot, port, cls, ingress);
+}
+
+static int seville_cls_flower_stats(struct dsa_switch *ds, int port,
+				  struct flow_cls_offload *cls, bool ingress)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_cls_flower_stats(ocelot, port, cls, ingress);
+}
+
+static int seville_port_policer_add(struct dsa_switch *ds, int port,
+				  struct dsa_mall_policer_tc_entry *policer)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct ocelot_policer pol = {
+		.rate = div_u64(policer->rate_bytes_per_sec, 1000) * 8,
+		.burst = div_u64(policer->rate_bytes_per_sec *
+				 PSCHED_NS2TICKS(policer->burst),
+				 PSCHED_TICKS_PER_SEC),
+	};
+
+	return ocelot_port_policer_add(ocelot, port, &pol);
+}
+
+static void seville_port_policer_del(struct dsa_switch *ds, int port)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	ocelot_port_policer_del(ocelot, port);
+}
+
+static const struct dsa_switch_ops seville_switch_ops = {
+	.get_tag_protocol	= seville_get_tag_protocol,
+	.setup			= seville_setup,
+	.teardown		= seville_teardown,
+	.set_ageing_time	= seville_set_ageing_time,
+	.get_strings		= seville_get_strings,
+	.get_ethtool_stats	= seville_get_ethtool_stats,
+	.get_sset_count		= seville_get_sset_count,
+	.phylink_validate	= seville_phylink_validate,
+	.phylink_mac_link_state	= seville_phylink_mac_pcs_get_state,
+	.phylink_mac_config	= seville_phylink_mac_config,
+	.phylink_mac_an_restart	= seville_phylink_mac_an_restart,
+	.phylink_mac_link_down	= seville_phylink_mac_link_down,
+	.phylink_mac_link_up	= seville_phylink_mac_link_up,
+	.port_enable		= seville_port_enable,
+	.port_disable		= seville_port_disable,
+	.port_fdb_dump		= seville_fdb_dump,
+	.port_fdb_add		= seville_fdb_add,
+	.port_fdb_del		= seville_fdb_del,
+	.port_bridge_join	= seville_bridge_join,
+	.port_bridge_leave	= seville_bridge_leave,
+	.port_stp_state_set	= seville_bridge_stp_state_set,
+	.port_vlan_prepare	= seville_vlan_prepare,
+	.port_vlan_filtering	= seville_vlan_filtering,
+	.port_vlan_add		= seville_vlan_add,
+	.port_vlan_del		= seville_vlan_del,
+	.port_change_mtu	= seville_change_mtu,
+	.port_max_mtu		= seville_get_max_mtu,
+	.port_policer_add	= seville_port_policer_add,
+	.port_policer_del	= seville_port_policer_del,
+	.cls_flower_add		= seville_cls_flower_add,
+	.cls_flower_del		= seville_cls_flower_del,
+	.cls_flower_stats	= seville_cls_flower_stats,
+};
+
+static int seville_probe(struct platform_device *pdev)
+{
+	struct dsa_switch *ds;
+	struct ocelot *ocelot;
+	struct seville *seville;
+	struct resource *res;
+	int err;
+
+	seville = kzalloc(sizeof(struct seville), GFP_KERNEL);
+	if (!seville) {
+		err = -ENOMEM;
+		dev_err(&pdev->dev, "Failed to allocate driver memory\n");
+		goto err_alloc_seville;
+	}
+
+	platform_set_drvdata(pdev, seville);
+
+	ocelot = &seville->ocelot;
+	ocelot->dev = &pdev->dev;
+	seville->pdev = pdev;
+	seville->info = &seville_info_vsc9953;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	seville->switch_base = res->start;
+
+	ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
+	if (!ds) {
+		err = -ENOMEM;
+		dev_err(&pdev->dev, "Failed to allocate DSA switch\n");
+		goto err_alloc_ds;
+	}
+
+	ds->dev = &pdev->dev;
+	ds->num_ports = seville->info->num_ports;
+	ds->ops = &seville_switch_ops;
+	ds->priv = ocelot;
+	seville->ds = ds;
+
+	err = dsa_register_switch(ds);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
+		goto err_register_ds;
+	}
+
+	return 0;
+
+err_register_ds:
+	kfree(ds);
+err_alloc_ds:
+err_alloc_seville:
+	kfree(seville);
+	return err;
+}
+
+static int seville_remove(struct platform_device *pdev)
+{
+	struct seville *seville;
+
+	seville = platform_get_drvdata(pdev);
+
+	dsa_unregister_switch(seville->ds);
+
+	kfree(seville->ds);
+	kfree(seville);
+
+	return 0;
+}
+
+static const struct of_device_id seville_of_match[] = {
+	{ .compatible = "mscc,vsc9953-switch" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, seville_of_match);
+
+static struct platform_driver seville_driver = {
+	.probe		= seville_probe,
+	.remove		= seville_remove,
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.of_match_table	= of_match_ptr(seville_of_match),
+	},
+};
+module_platform_driver(seville_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Maxim Kochetkov <fido_max@inbox.ru>");
+MODULE_DESCRIPTION("Seville Switch driver");
diff --git a/drivers/net/dsa/ocelot/seville.h b/drivers/net/dsa/ocelot/seville.h
new file mode 100644
index 000000000000..242e7ce27de9
--- /dev/null
+++ b/drivers/net/dsa/ocelot/seville.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Distributed Switch Architecture VSC9953 driver
+ * Copyright (C) 2020, Maxim Kochetkov <fido_max@inbox.ru>
+ */
+#ifndef _MSCC_SEVILLE_H
+#define _MSCC_SEVILLE_H
+
+#define ocelot_to_seville(o)		container_of((o), struct seville, ocelot)
+
+/* Platform-specific information */
+struct seville_info {
+	const struct resource		*target_io_res;
+	const struct resource		*port_io_res;
+	const struct reg_field		*regfields;
+	const u32 *const		*map;
+	const struct ocelot_ops		*ops;
+	int				shared_queue_sz;
+	int				num_mact_rows;
+	const struct ocelot_stat_layout	*stats_layout;
+	unsigned int			num_stats;
+	int				num_ports;
+	struct vcap_field		*vcap_is2_keys;
+	struct vcap_field		*vcap_is2_actions;
+	const struct vcap_props		*vcap;
+	int	(*mdio_bus_alloc)(struct ocelot *ocelot);
+	void	(*mdio_bus_free)(struct ocelot *ocelot);
+	void	(*pcs_init)(struct ocelot *ocelot, int port,
+			    unsigned int link_an_mode,
+			    const struct phylink_link_state *state);
+	void	(*pcs_an_restart)(struct ocelot *ocelot, int port);
+	void	(*pcs_link_state)(struct ocelot *ocelot, int port,
+				  struct phylink_link_state *state);
+	int	(*prevalidate_phy_mode)(struct ocelot *ocelot, int port,
+					phy_interface_t phy_mode);
+};
+
+extern struct seville_info		seville_info_vsc9953;
+
+/* DSA glue / front-end for struct ocelot */
+struct seville {
+	struct dsa_switch		*ds;
+	struct platform_device			*pdev;
+	struct seville_info		*info;
+	struct ocelot			ocelot;
+	resource_size_t switch_base;
+	struct mii_bus			*imdio;
+	struct phy_device		**pcs;
+};
+
+#endif
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
new file mode 100644
index 000000000000..e40d3a318a14
--- /dev/null
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -0,0 +1,1064 @@
+// 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_vcap.h>
+#include <soc/mscc/ocelot_sys.h>
+#include <soc/mscc/ocelot.h>
+#include <linux/iopoll.h>
+#include <linux/pci.h>
+#include "seville.h"
+
+#define VSC9953_VCAP_IS2_CNT		1024
+#define VSC9953_VCAP_IS2_ENTRY_WIDTH	376
+#define VSC9953_VCAP_PORT_CNT		10
+
+/* PCS registers */
+#define MDIO_SGMII_DEV_ABIL_SGMII	0x04
+#define MDIO_SGMII_LINK_TMR_L		0x12
+#define MDIO_SGMII_LINK_TMR_H		0x13
+#define MDIO_SGMII_IF_MODE		0x14
+
+/* SGMII Control defines */
+#define SGMII_CR_AN_EN			0x1000
+#define SGMII_CR_RESTART_AN		0x0200
+#define SGMII_CR_FD			0x0100
+#define SGMII_CR_SPEED_SEL1_1G		0x0040
+#define SGMII_CR_DEF_VAL		(SGMII_CR_AN_EN | SGMII_CR_FD | \
+					 SGMII_CR_SPEED_SEL1_1G)
+
+/* SGMII Device Ability for SGMII defines */
+#define MDIO_SGMII_DEV_ABIL_SGMII_MODE	0x01a1
+#define MDIO_SGMII_DEV_ABIL_BASEX_MODE	0x01A0
+
+/* SGMII IF Mode defines */
+#define IF_MODE_USE_SGMII_AN		0x0002
+#define IF_MODE_SGMII_EN		0x0001
+#define IF_MODE_SGMII_SPEED_100M	0x0004
+#define IF_MODE_SGMII_SPEED_1G		0x0008
+#define IF_MODE_SGMII_DUPLEX_HALF	0x0010
+
+#define MSCC_MIIM_REG_STATUS		0x0
+#define		MSCC_MIIM_STATUS_STAT_BUSY	BIT(3)
+#define MSCC_MIIM_REG_CMD		0x8
+#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)
+#define MSCC_MIIM_REG_DATA		0xC
+#define		MSCC_MIIM_DATA_ERROR		(BIT(16) | BIT(17))
+
+#define MSCC_PHY_REG_PHY_CFG	0x0
+#define		PHY_CFG_PHY_ENA		(BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define		PHY_CFG_PHY_COMMON_RESET BIT(4)
+#define		PHY_CFG_PHY_RESET	(BIT(5) | BIT(6) | BIT(7) | BIT(8))
+#define MSCC_PHY_REG_PHY_STATUS	0x4
+
+static const u32 vsc9953_ana_regmap[] = {
+	REG(ANA_ADVLEARN,			0x00b500),
+	REG(ANA_VLANMASK,			0x00b504),
+	REG_RESERVED(ANA_PORT_B_DOMAIN),
+	REG(ANA_ANAGEFIL,			0x00b50c),
+	REG(ANA_ANEVENTS,			0x00b510),
+	REG(ANA_STORMLIMIT_BURST,		0x00b514),
+	REG(ANA_STORMLIMIT_CFG,			0x00b518),
+	REG(ANA_ISOLATED_PORTS,			0x00b528),
+	REG(ANA_COMMUNITY_PORTS,		0x00b52c),
+	REG(ANA_AUTOAGE,			0x00b530),
+	REG(ANA_MACTOPTIONS,			0x00b534),
+	REG(ANA_LEARNDISC,			0x00b538),
+	REG(ANA_AGENCTRL,			0x00b53c),
+	REG(ANA_MIRRORPORTS,			0x00b540),
+	REG(ANA_EMIRRORPORTS,			0x00b544),
+	REG(ANA_FLOODING,			0x00b548),
+	REG(ANA_FLOODING_IPMC,			0x00b54c),
+	REG(ANA_SFLOW_CFG,			0x00b550),
+	REG(ANA_PORT_MODE,			0x00b57c),
+	REG_RESERVED(ANA_CUT_THRU_CFG),
+	REG(ANA_PGID_PGID,			0x00b600),
+	REG(ANA_TABLES_ANMOVED,			0x00b4ac),
+	REG(ANA_TABLES_MACHDATA,		0x00b4b0),
+	REG(ANA_TABLES_MACLDATA,		0x00b4b4),
+	REG_RESERVED(ANA_TABLES_STREAMDATA),
+	REG(ANA_TABLES_MACACCESS,		0x00b4b8),
+	REG(ANA_TABLES_MACTINDX,		0x00b4bc),
+	REG(ANA_TABLES_VLANACCESS,		0x00b4c0),
+	REG(ANA_TABLES_VLANTIDX,		0x00b4c4),
+	REG_RESERVED(ANA_TABLES_ISDXACCESS),
+	REG_RESERVED(ANA_TABLES_ISDXTIDX),
+	REG(ANA_TABLES_ENTRYLIM,		0x00b480),
+	REG_RESERVED(ANA_TABLES_PTP_ID_HIGH),
+	REG_RESERVED(ANA_TABLES_PTP_ID_LOW),
+	REG_RESERVED(ANA_TABLES_STREAMACCESS),
+	REG_RESERVED(ANA_TABLES_STREAMTIDX),
+	REG_RESERVED(ANA_TABLES_SEQ_HISTORY),
+	REG_RESERVED(ANA_TABLES_SEQ_MASK),
+	REG_RESERVED(ANA_TABLES_SFID_MASK),
+	REG_RESERVED(ANA_TABLES_SFIDACCESS),
+	REG_RESERVED(ANA_TABLES_SFIDTIDX),
+	REG_RESERVED(ANA_MSTI_STATE),
+	REG_RESERVED(ANA_OAM_UPM_LM_CNT),
+	REG_RESERVED(ANA_SG_ACCESS_CTRL),
+	REG_RESERVED(ANA_SG_CONFIG_REG_1),
+	REG_RESERVED(ANA_SG_CONFIG_REG_2),
+	REG_RESERVED(ANA_SG_CONFIG_REG_3),
+	REG_RESERVED(ANA_SG_CONFIG_REG_4),
+	REG_RESERVED(ANA_SG_CONFIG_REG_5),
+	REG_RESERVED(ANA_SG_GCL_GS_CONFIG),
+	REG_RESERVED(ANA_SG_GCL_TI_CONFIG),
+	REG_RESERVED(ANA_SG_STATUS_REG_1),
+	REG_RESERVED(ANA_SG_STATUS_REG_2),
+	REG_RESERVED(ANA_SG_STATUS_REG_3),
+	REG(ANA_PORT_VLAN_CFG,			0x000000),
+	REG(ANA_PORT_DROP_CFG,			0x000004),
+	REG(ANA_PORT_QOS_CFG,			0x000008),
+	REG(ANA_PORT_VCAP_CFG,			0x00000c),
+	REG(ANA_PORT_VCAP_S1_KEY_CFG,		0x000010),
+	REG(ANA_PORT_VCAP_S2_CFG,		0x00001c),
+	REG(ANA_PORT_PCP_DEI_MAP,		0x000020),
+	REG(ANA_PORT_CPU_FWD_CFG,		0x000060),
+	REG(ANA_PORT_CPU_FWD_BPDU_CFG,		0x000064),
+	REG(ANA_PORT_CPU_FWD_GARP_CFG,		0x000068),
+	REG(ANA_PORT_CPU_FWD_CCM_CFG,		0x00006c),
+	REG(ANA_PORT_PORT_CFG,			0x000070),
+	REG(ANA_PORT_POL_CFG,			0x000074),
+	REG_RESERVED(ANA_PORT_PTP_CFG),
+	REG_RESERVED(ANA_PORT_PTP_DLY1_CFG),
+	REG_RESERVED(ANA_PORT_PTP_DLY2_CFG),
+	REG_RESERVED(ANA_PORT_SFID_CFG),
+	REG(ANA_PFC_PFC_CFG,			0x00c000),
+	REG_RESERVED(ANA_PFC_PFC_TIMER),
+	REG_RESERVED(ANA_IPT_OAM_MEP_CFG),
+	REG_RESERVED(ANA_IPT_IPT),
+	REG_RESERVED(ANA_PPT_PPT),
+	REG_RESERVED(ANA_FID_MAP_FID_MAP),
+	REG(ANA_AGGR_CFG,			0x00c600),
+	REG(ANA_CPUQ_CFG,			0x00c604),
+	REG_RESERVED(ANA_CPUQ_CFG2),
+	REG(ANA_CPUQ_8021_CFG,			0x00c60c),
+	REG(ANA_DSCP_CFG,			0x00c64c),
+	REG(ANA_DSCP_REWR_CFG,			0x00c74c),
+	REG(ANA_VCAP_RNG_TYPE_CFG,		0x00c78c),
+	REG(ANA_VCAP_RNG_VAL_CFG,		0x00c7ac),
+	REG_RESERVED(ANA_VRAP_CFG),
+	REG_RESERVED(ANA_VRAP_HDR_DATA),
+	REG_RESERVED(ANA_VRAP_HDR_MASK),
+	REG(ANA_DISCARD_CFG,			0x00c7d8),
+	REG(ANA_FID_CFG,			0x00c7dc),
+	REG(ANA_POL_PIR_CFG,			0x00a000),
+	REG(ANA_POL_CIR_CFG,			0x00a004),
+	REG(ANA_POL_MODE_CFG,			0x00a008),
+	REG(ANA_POL_PIR_STATE,			0x00a00c),
+	REG(ANA_POL_CIR_STATE,			0x00a010),
+	REG_RESERVED(ANA_POL_STATE),
+	REG(ANA_POL_FLOWC,			0x00c280),
+	REG(ANA_POL_HYST,			0x00c2ec),
+	REG_RESERVED(ANA_POL_MISC_CFG),
+};
+
+static const u32 vsc9953_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_RESERVED(QS_INH_DBG),
+};
+
+static const u32 vsc9953_s2_regmap[] = {
+	REG(S2_CORE_UPDATE_CTRL,		0x000000),
+	REG(S2_CORE_MV_CFG,			0x000004),
+	REG(S2_CACHE_ENTRY_DAT,			0x000008),
+	REG(S2_CACHE_MASK_DAT,			0x000108),
+	REG(S2_CACHE_ACTION_DAT,		0x000208),
+	REG(S2_CACHE_CNT_DAT,			0x000308),
+	REG(S2_CACHE_TG_DAT,			0x000388),
+};
+
+static const u32 vsc9953_qsys_regmap[] = {
+	REG(QSYS_PORT_MODE,			0x003600),
+	REG(QSYS_SWITCH_PORT_MODE,		0x003630),
+	REG(QSYS_STAT_CNT_CFG,			0x00365c),
+	REG(QSYS_EEE_CFG,			0x003660),
+	REG(QSYS_EEE_THRES,			0x003688),
+	REG(QSYS_IGR_NO_SHARING,		0x00368c),
+	REG(QSYS_EGR_NO_SHARING,		0x003690),
+	REG(QSYS_SW_STATUS,			0x003694),
+	REG(QSYS_EXT_CPU_CFG,			0x0036c0),
+	REG_RESERVED(QSYS_PAD_CFG),
+	REG(QSYS_CPU_GROUP_MAP,			0x0036c8),
+	REG_RESERVED(QSYS_QMAP),
+	REG_RESERVED(QSYS_ISDX_SGRP),
+	REG_RESERVED(QSYS_TIMED_FRAME_ENTRY),
+	REG_RESERVED(QSYS_TFRM_MISC),
+	REG_RESERVED(QSYS_TFRM_PORT_DLY),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_1),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_2),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_3),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_4),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_5),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_6),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_7),
+	REG_RESERVED(QSYS_TFRM_TIMER_CFG_8),
+	REG(QSYS_RED_PROFILE,			0x003724),
+	REG(QSYS_RES_QOS_MODE,			0x003764),
+	REG(QSYS_RES_CFG,			0x004000),
+	REG(QSYS_RES_STAT,			0x004004),
+	REG(QSYS_EGR_DROP_MODE,			0x003768),
+	REG(QSYS_EQ_CTRL,			0x00376c),
+	REG_RESERVED(QSYS_EVENTS_CORE),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_0),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_1),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_2),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_3),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_4),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_5),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_6),
+	REG_RESERVED(QSYS_QMAXSDU_CFG_7),
+	REG_RESERVED(QSYS_PREEMPTION_CFG),
+	REG(QSYS_CIR_CFG,			0x000000),
+	REG_RESERVED(QSYS_EIR_CFG),
+	REG(QSYS_SE_CFG,			0x000008),
+	REG(QSYS_SE_DWRR_CFG,			0x00000c),
+	REG_RESERVED(QSYS_SE_CONNECT),
+	REG_RESERVED(QSYS_SE_DLB_SENSE),
+	REG(QSYS_CIR_STATE,			0x000044),
+	REG_RESERVED(QSYS_EIR_STATE),
+	REG_RESERVED(QSYS_SE_STATE),
+	REG(QSYS_HSCH_MISC_CFG,			0x003774),
+	REG_RESERVED(QSYS_TAG_CONFIG),
+	REG_RESERVED(QSYS_TAS_PARAM_CFG_CTRL),
+	REG_RESERVED(QSYS_PORT_MAX_SDU),
+	REG_RESERVED(QSYS_PARAM_CFG_REG_1),
+	REG_RESERVED(QSYS_PARAM_CFG_REG_2),
+	REG_RESERVED(QSYS_PARAM_CFG_REG_3),
+	REG_RESERVED(QSYS_PARAM_CFG_REG_4),
+	REG_RESERVED(QSYS_PARAM_CFG_REG_5),
+	REG_RESERVED(QSYS_GCL_CFG_REG_1),
+	REG_RESERVED(QSYS_GCL_CFG_REG_2),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_1),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_2),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_3),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_4),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_5),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_6),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_7),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_8),
+	REG_RESERVED(QSYS_PARAM_STATUS_REG_9),
+	REG_RESERVED(QSYS_GCL_STATUS_REG_1),
+	REG_RESERVED(QSYS_GCL_STATUS_REG_2),
+};
+
+static const u32 vsc9953_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_RESERVED(REW_PTP_CFG),
+	REG_RESERVED(REW_PTP_DLY1_CFG),
+	REG_RESERVED(REW_RED_TAG_CFG),
+	REG(REW_DSCP_REMAP_DP1_CFG,		0x000610),
+	REG(REW_DSCP_REMAP_CFG,			0x000710),
+	REG_RESERVED(REW_STAT_CFG),
+	REG_RESERVED(REW_REW_STICKY),
+	REG_RESERVED(REW_PPT),
+};
+
+static const u32 vsc9953_sys_regmap[] = {
+	REG(SYS_COUNT_RX_OCTETS,		0x000000),
+	REG(SYS_COUNT_RX_MULTICAST,		0x000008),
+	REG(SYS_COUNT_RX_SHORTS,		0x000010),
+	REG(SYS_COUNT_RX_FRAGMENTS,		0x000014),
+	REG(SYS_COUNT_RX_JABBERS,		0x000018),
+	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_LONGS,			0x000048),
+	REG(SYS_COUNT_TX_OCTETS,		0x000100),
+	REG(SYS_COUNT_TX_COLLISION,		0x000110),
+	REG(SYS_COUNT_TX_DROPS,			0x000114),
+	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,			0x000178),
+	REG(SYS_RESET_CFG,			0x000318),
+	REG_RESERVED(SYS_SR_ETYPE_CFG),
+	REG(SYS_VLAN_ETYPE_CFG,			0x000320),
+	REG(SYS_PORT_MODE,			0x000324),
+	REG(SYS_FRONT_PORT_MODE,		0x000354),
+	REG(SYS_FRM_AGING,			0x00037c),
+	REG(SYS_STAT_CFG,			0x000380),
+	REG_RESERVED(SYS_SW_STATUS),
+	REG_RESERVED(SYS_MISC_CFG),
+	REG_RESERVED(SYS_REW_MAC_HIGH_CFG),
+	REG_RESERVED(SYS_REW_MAC_LOW_CFG),
+	REG_RESERVED(SYS_TIMESTAMP_OFFSET),
+	REG(SYS_PAUSE_CFG,			0x00044c),
+	REG(SYS_PAUSE_TOT_CFG,			0x000478),
+	REG(SYS_ATOP,				0x00047c),
+	REG(SYS_ATOP_TOT_CFG,			0x0004a8),
+	REG(SYS_MAC_FC_CFG,			0x0004ac),
+	REG(SYS_MMGT,				0x0004d4),
+	REG_RESERVED(SYS_MMGT_FAST),
+	REG_RESERVED(SYS_EVENTS_DIF),
+	REG_RESERVED(SYS_EVENTS_CORE),
+	REG_RESERVED(SYS_CNT),
+	REG_RESERVED(SYS_PTP_STATUS),
+	REG_RESERVED(SYS_PTP_TXSTAMP),
+	REG_RESERVED(SYS_PTP_NXT),
+	REG_RESERVED(SYS_PTP_CFG),
+	REG_RESERVED(SYS_RAM_INIT),
+	REG_RESERVED(SYS_CM_ADDR),
+	REG_RESERVED(SYS_CM_DATA_WR),
+	REG_RESERVED(SYS_CM_DATA_RD),
+	REG_RESERVED(SYS_CM_OP),
+	REG_RESERVED(SYS_CM_DATA),
+};
+
+static const u32 vsc9953_gcb_regmap[] = {
+	REG(GCB_SOFT_RST,			0x000008),
+	REG(GCB_MIIM_MII_STATUS,		0x0000ac),
+	REG(GCB_MIIM_MII_CMD,			0x0000b4),
+	REG(GCB_MIIM_MII_DATA,			0x0000b8),
+};
+
+static const u32 vsc9953_dev_gmii_regmap[] = {
+	REG(DEV_CLOCK_CFG,			0x0),
+	REG(DEV_PORT_MISC,			0x4),
+	REG_RESERVED(DEV_EVENTS),
+	REG(DEV_EEE_CFG,			0xc),
+	REG_RESERVED(DEV_RX_PATH_DELAY),
+	REG_RESERVED(DEV_TX_PATH_DELAY),
+	REG_RESERVED(DEV_PTP_PREDICT_CFG),
+	REG(DEV_MAC_ENA_CFG,			0x10),
+	REG(DEV_MAC_MODE_CFG,			0x14),
+	REG(DEV_MAC_MAXLEN_CFG,			0x18),
+	REG(DEV_MAC_TAGS_CFG,			0x1c),
+	REG(DEV_MAC_ADV_CHK_CFG,		0x20),
+	REG(DEV_MAC_IFG_CFG,			0x24),
+	REG(DEV_MAC_HDX_CFG,			0x28),
+	REG_RESERVED(DEV_MAC_DBG_CFG),
+	REG(DEV_MAC_FC_MAC_LOW_CFG,		0x30),
+	REG(DEV_MAC_FC_MAC_HIGH_CFG,		0x34),
+	REG(DEV_MAC_STICKY,			0x38),
+	REG_RESERVED(PCS1G_CFG),
+	REG_RESERVED(PCS1G_MODE_CFG),
+	REG_RESERVED(PCS1G_SD_CFG),
+	REG_RESERVED(PCS1G_ANEG_CFG),
+	REG_RESERVED(PCS1G_ANEG_NP_CFG),
+	REG_RESERVED(PCS1G_LB_CFG),
+	REG_RESERVED(PCS1G_DBG_CFG),
+	REG_RESERVED(PCS1G_CDET_CFG),
+	REG_RESERVED(PCS1G_ANEG_STATUS),
+	REG_RESERVED(PCS1G_ANEG_NP_STATUS),
+	REG_RESERVED(PCS1G_LINK_STATUS),
+	REG_RESERVED(PCS1G_LINK_DOWN_CNT),
+	REG_RESERVED(PCS1G_STICKY),
+	REG_RESERVED(PCS1G_DEBUG_STATUS),
+	REG_RESERVED(PCS1G_LPI_CFG),
+	REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT),
+	REG_RESERVED(PCS1G_LPI_STATUS),
+	REG_RESERVED(PCS1G_TSTPAT_MODE_CFG),
+	REG_RESERVED(PCS1G_TSTPAT_STATUS),
+	REG_RESERVED(DEV_PCS_FX100_CFG),
+	REG_RESERVED(DEV_PCS_FX100_STATUS),
+};
+
+static const u32 *vsc9953_regmap[] = {
+	[ANA]	= vsc9953_ana_regmap,
+	[QS]	= vsc9953_qs_regmap,
+	[QSYS]	= vsc9953_qsys_regmap,
+	[REW]	= vsc9953_rew_regmap,
+	[SYS]	= vsc9953_sys_regmap,
+	[S2]	= vsc9953_s2_regmap,
+	[GCB]	= vsc9953_gcb_regmap,
+	[DEV_GMII] = vsc9953_dev_gmii_regmap,
+};
+
+/* Addresses are relative to the device's base address */
+static const struct resource vsc9953_target_io_res[TARGET_MAX] = {
+	[ANA] = {
+		.start	= 0x0280000,
+		.end	= 0x028ffff,
+		.name	= "ana",
+	},
+	[QS] = {
+		.start	= 0x0080000,
+		.end	= 0x00800ff,
+		.name	= "qs",
+	},
+	[QSYS] = {
+		.start	= 0x0200000,
+		.end	= 0x021ffff,
+		.name	= "qsys",
+	},
+	[REW] = {
+		.start	= 0x0030000,
+		.end	= 0x003ffff,
+		.name	= "rew",
+	},
+	[SYS] = {
+		.start	= 0x0010000,
+		.end	= 0x001ffff,
+		.name	= "sys",
+	},
+	[S2] = {
+		.start	= 0x0060000,
+		.end	= 0x00603ff,
+		.name	= "s2",
+	},
+	[PTP] = {
+		.start	= 0x0090000,
+		.end	= 0x00900cb,
+		.name	= "ptp",
+	},
+	[GCB] = {
+		.start	= 0x0070000,
+		.end	= 0x00701ff,
+		.name	= "devcpu_gcb",
+	},
+};
+
+static const struct resource vsc9953_port_io_res[] = {
+	{
+		.start	= 0x0100000,
+		.end	= 0x010ffff,
+		.name	= "port0",
+	},
+	{
+		.start	= 0x0110000,
+		.end	= 0x011ffff,
+		.name	= "port1",
+	},
+	{
+		.start	= 0x0120000,
+		.end	= 0x012ffff,
+		.name	= "port2",
+	},
+	{
+		.start	= 0x0130000,
+		.end	= 0x013ffff,
+		.name	= "port3",
+	},
+	{
+		.start	= 0x0140000,
+		.end	= 0x014ffff,
+		.name	= "port4",
+	},
+	{
+		.start	= 0x0150000,
+		.end	= 0x015ffff,
+		.name	= "port5",
+	},
+	{
+		.start	= 0x0160000,
+		.end	= 0x016ffff,
+		.name	= "port6",
+	},
+	{
+		.start	= 0x0170000,
+		.end	= 0x017ffff,
+		.name	= "port7",
+	},
+	{
+		.start	= 0x0180000,
+		.end	= 0x018ffff,
+		.name	= "port8",
+	},
+	{
+		.start	= 0x0190000,
+		.end	= 0x019ffff,
+		.name	= "port9",
+	},
+};
+
+static const struct reg_field vsc9953_regfields[] = {
+	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 10, 10),
+	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 9),
+	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24),
+	[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_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, 16, 16),
+	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 11, 12),
+	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10),
+	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 7, 7),
+	[SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 6, 6),
+	[SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 5, 5),
+	[GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0),
+	[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),
+	/* Replicated per number of ports (11), register size 4 per port */
+	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 13, 13, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 11, 4),
+	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 11, 4),
+	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 4, 5, 11, 4),
+	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 2, 3, 11, 4),
+	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 11, 4),
+	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 11, 20, 11, 4),
+	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 10, 11, 4),
+	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 11, 4),
+};
+
+static const struct ocelot_stat_layout vsc9953_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", },
+};
+
+struct vcap_field vsc9953_vcap_is2_keys[] = {
+	/* Common: 41 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,  11},
+	[VCAP_IS2_HK_RSV2]			= { 24,   1},
+	[VCAP_IS2_HK_HOST_MATCH]		= { 25,   1},
+	[VCAP_IS2_HK_L2_MC]			= { 26,   1},
+	[VCAP_IS2_HK_L2_BC]			= { 27,   1},
+	[VCAP_IS2_HK_VLAN_TAGGED]		= { 28,   1},
+	[VCAP_IS2_HK_VID]			= { 29,  12},
+	[VCAP_IS2_HK_DEI]			= { 41,   1},
+	[VCAP_IS2_HK_PCP]			= { 42,   3},
+	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
+	[VCAP_IS2_HK_L2_DMAC]			= { 45,  48},
+	[VCAP_IS2_HK_L2_SMAC]			= { 93,  48},
+	/* MAC_ETYPE (TYPE=000) */
+	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= {141,  16},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= {157,  16},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= {173,   8},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= {181,   3},
+	/* MAC_LLC (TYPE=001) */
+	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= {141,  40},
+	/* MAC_SNAP (TYPE=010) */
+	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= {141,  40},
+	/* MAC_ARP (TYPE=011) */
+	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 45,  48},
+	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 93,   1},
+	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 94,   1},
+	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 95,   1},
+	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 96,   1},
+	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 97,   1},
+	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 98,   1},
+	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= { 99,   2},
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= {101,  32},
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= {133,  32},
+	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= {165,   1},
+	/* IP4_TCP_UDP / IP4_OTHER common */
+	[VCAP_IS2_HK_IP4]			= { 45,   1},
+	[VCAP_IS2_HK_L3_FRAGMENT]		= { 46,   1},
+	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 47,   1},
+	[VCAP_IS2_HK_L3_OPTIONS]		= { 48,   1},
+	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 49,   1},
+	[VCAP_IS2_HK_L3_TOS]			= { 50,   8},
+	[VCAP_IS2_HK_L3_IP4_DIP]		= { 58,  32},
+	[VCAP_IS2_HK_L3_IP4_SIP]		= { 90,  32},
+	[VCAP_IS2_HK_DIP_EQ_SIP]		= {122,   1},
+	/* IP4_TCP_UDP (TYPE=100) */
+	[VCAP_IS2_HK_TCP]			= {123,   1},
+	[VCAP_IS2_HK_L4_SPORT]			= {124,  16},
+	[VCAP_IS2_HK_L4_DPORT]			= {140,  16},
+	[VCAP_IS2_HK_L4_RNG]			= {156,   8},
+	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= {164,   1},
+	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= {165,   1},
+	[VCAP_IS2_HK_L4_URG]			= {166,   1},
+	[VCAP_IS2_HK_L4_ACK]			= {167,   1},
+	[VCAP_IS2_HK_L4_PSH]			= {168,   1},
+	[VCAP_IS2_HK_L4_RST]			= {169,   1},
+	[VCAP_IS2_HK_L4_SYN]			= {170,   1},
+	[VCAP_IS2_HK_L4_FIN]			= {171,   1},
+	/* IP4_OTHER (TYPE=101) */
+	[VCAP_IS2_HK_IP4_L3_PROTO]		= {123,   8},
+	[VCAP_IS2_HK_L3_PAYLOAD]		= {131,  56},
+	/* IP6_STD (TYPE=110) */
+	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 45,   1},
+	[VCAP_IS2_HK_L3_IP6_SIP]		= { 46, 128},
+	[VCAP_IS2_HK_IP6_L3_PROTO]		= {174,   8},
+};
+
+struct vcap_field vsc9953_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,  8},
+	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 21,  1},
+	[VCAP_IS2_ACT_PORT_MASK]		= { 22, 10},
+	[VCAP_IS2_ACT_ACL_ID]			= { 44,  6},
+	[VCAP_IS2_ACT_HIT_CNT]			= { 50, 32},
+};
+
+static const struct vcap_props vsc9953_vcap_props[] = {
+	[VCAP_IS2] = {
+		.tg_width = 2,
+		.sw_count = 4,
+		.entry_count = VSC9953_VCAP_IS2_CNT,
+		.entry_width = VSC9953_VCAP_IS2_ENTRY_WIDTH,
+		.action_count = VSC9953_VCAP_IS2_CNT +
+				VSC9953_VCAP_PORT_CNT + 2,
+		.action_width = 101,
+		.action_type_width = 1,
+		.action_table = {
+			[IS2_ACTION_TYPE_NORMAL] = {
+				.width = 44,
+				.count = 2
+			},
+			[IS2_ACTION_TYPE_SMAC_SIP] = {
+				.width = 6,
+				.count = 4
+			},
+		},
+		.counter_words = 4,
+		.counter_width = 32,
+	},
+};
+
+#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)
+{
+	int val;
+
+	ocelot_field_read(ocelot, GCB_SOFT_RST_SWC_RST, &val);
+
+	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_sys_ram_init_status(struct ocelot *ocelot)
+{
+	int val;
+
+	ocelot_field_read(ocelot, SYS_RESET_CFG_MEM_INIT, &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)
+{
+	int err, cmd, val;
+	struct ocelot *ocelot = bus->priv;
+
+	/* 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;
+}
+
+static int vsc9953_reset(struct ocelot *ocelot)
+{
+	int val, err;
+
+	/* soft-reset the switch core */
+	ocelot_field_write(ocelot, GCB_SOFT_RST_SWC_RST, 1);
+
+	err = readx_poll_timeout(vsc9953_gcb_soft_rst_status, ocelot, val, !val,
+				 VSC9953_GCB_RST_SLEEP, VSC9953_INIT_TIMEOUT);
+	if (err) {
+		dev_err(ocelot->dev, "timeout: switch core reset\n");
+		return err;
+	}
+
+	/* initialize switch mem ~40us */
+	ocelot_field_write(ocelot, SYS_RESET_CFG_MEM_INIT, 1);
+	ocelot_field_write(ocelot, SYS_RESET_CFG_MEM_ENA, 1);
+
+	err = readx_poll_timeout(vsc9953_sys_ram_init_status, ocelot, val, !val,
+				 VSC9953_SYS_RAMINIT_SLEEP,
+				 VSC9953_INIT_TIMEOUT);
+	if (err) {
+		dev_err(ocelot->dev, "timeout: switch sram init\n");
+		return err;
+	}
+
+	/* enable switch core */
+	ocelot_field_write(ocelot, SYS_RESET_CFG_MEM_ENA, 1);
+	ocelot_field_write(ocelot, SYS_RESET_CFG_CORE_ENA, 1);
+
+	return 0;
+}
+
+static void vsc9953_pcs_init_sgmii(struct phy_device *pcs,
+				   unsigned int link_an_mode,
+				   const struct phylink_link_state *state)
+{
+	/* Interface Mode Register */
+	phy_write(pcs, MDIO_SGMII_IF_MODE,
+		  IF_MODE_SGMII_EN | IF_MODE_USE_SGMII_AN);
+	/* Device Ability Register */
+	phy_write(pcs, MII_ADVERTISE, MDIO_SGMII_DEV_ABIL_SGMII_MODE);
+	/* Adjust link timer for SGMII
+	 * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
+	 */
+	/* Timer Upper Register */
+	phy_write(pcs, MDIO_SGMII_LINK_TMR_H, 0x0003);
+	/* Timer Lower Register */
+	phy_write(pcs, MDIO_SGMII_LINK_TMR_L, 0x0d40);
+	/* Control Register */
+	phy_write(pcs, MII_BMCR, SGMII_CR_DEF_VAL);
+}
+
+static void vsc9953_pcs_init(struct ocelot *ocelot, int port,
+			     unsigned int link_an_mode,
+			     const struct phylink_link_state *state)
+{
+	struct seville *seville = ocelot_to_seville(ocelot);
+	struct phy_device *pcs = seville->pcs[port];
+
+	if (!pcs)
+		return;
+
+	/* The PCS does not implement the BMSR register fully, so capability
+	 * detection via genphy_read_abilities does not work. Since we can get
+	 * the PHY config word from the LPA register though, there is still
+	 * value in using the generic phy_resolve_aneg_linkmode function. So
+	 * populate the supported and advertising link modes manually here.
+	 */
+	linkmode_set_bit_array(phy_basic_ports_array,
+			       ARRAY_SIZE(phy_basic_ports_array),
+			       pcs->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pcs->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pcs->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pcs->supported);
+	if (pcs->interface == PHY_INTERFACE_MODE_2500BASEX)
+		linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+				 pcs->supported);
+	if (pcs->interface != PHY_INTERFACE_MODE_2500BASEX)
+		linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+				 pcs->supported);
+	phy_advertise_supported(pcs);
+
+	switch (pcs->interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_QSGMII:
+		vsc9953_pcs_init_sgmii(pcs, link_an_mode, state);
+		break;
+	default:
+		dev_err(ocelot->dev, "Unsupported link mode %s\n",
+			phy_modes(pcs->interface));
+	}
+}
+
+static int vsc9953_prevalidate_phy_mode(struct ocelot *ocelot, int port,
+					phy_interface_t phy_mode)
+{
+	switch (phy_mode) {
+	case PHY_INTERFACE_MODE_INTERNAL:
+		if (port != 8 && port != 9)
+			return -ENOTSUPP;
+		return 0;
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_QSGMII:
+	case PHY_INTERFACE_MODE_2500BASEX:
+		/* Not supported on internal to-CPU ports */
+		if (port == 8 || port == 9)
+			return -ENOTSUPP;
+		return 0;
+	default:
+		return -ENOTSUPP;
+	}
+}
+
+/* Watermark encode
+ * Bit 9:   Unit; 0:1, 1:16
+ * Bit 8-0: Value to be multiplied with unit
+ */
+static u16 seville_wm_enc(u16 value)
+{
+	if (value >= BIT(9))
+		return BIT(9) | (value / 16);
+
+	return value;
+}
+
+static const struct ocelot_ops vsc9953_ops = {
+	.reset			= vsc9953_reset,
+	.wm_enc			= seville_wm_enc,
+};
+
+static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
+{
+	struct seville *seville = ocelot_to_seville(ocelot);
+	struct device *dev = ocelot->dev;
+	struct mii_bus *bus;
+	int port;
+	int rc;
+
+	seville->pcs = devm_kcalloc(dev, seville->info->num_ports,
+				  sizeof(struct phy_device *),
+				  GFP_KERNEL);
+	if (!seville->pcs) {
+		dev_err(dev, "failed to allocate array for PCS PHYs\n");
+		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));
+
+	/* Needed in order to initialize the bus mutex lock */
+	rc = mdiobus_register(bus);
+	if (rc < 0) {
+		dev_err(dev, "failed to register MDIO bus\n");
+		return rc;
+	}
+
+	seville->imdio = bus;
+
+	for (port = 0; port < seville->info->num_ports; port++) {
+		struct ocelot_port *ocelot_port = ocelot->ports[port];
+		struct phy_device *pcs;
+
+		pcs = get_phy_device(seville->imdio, port + 4, false);
+		if (IS_ERR(pcs))
+			continue;
+
+		pcs->interface = ocelot_port->phy_mode;
+		seville->pcs[port] = pcs;
+
+		dev_info(dev, "Found PCS at internal MDIO address %d\n",
+			 port + 4);
+	}
+
+	return 0;
+}
+
+static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
+{
+	struct seville *seville = ocelot_to_seville(ocelot);
+	int port;
+
+	for (port = 0; port < ocelot->num_phys_ports; port++) {
+		struct phy_device *pcs = seville->pcs[port];
+
+		if (!pcs)
+			continue;
+
+		put_device(&pcs->mdio.dev);
+	}
+	mdiobus_unregister(seville->imdio);
+}
+
+struct seville_info seville_info_vsc9953 = {
+	.target_io_res		= vsc9953_target_io_res,
+	.port_io_res		= vsc9953_port_io_res,
+	.regfields		= vsc9953_regfields,
+	.map			= vsc9953_regmap,
+	.ops			= &vsc9953_ops,
+	.stats_layout		= vsc9953_stats_layout,
+	.num_stats		= ARRAY_SIZE(vsc9953_stats_layout),
+	.vcap_is2_keys		= vsc9953_vcap_is2_keys,
+	.vcap_is2_actions	= vsc9953_vcap_is2_actions,
+	.vcap			= vsc9953_vcap_props,
+	.shared_queue_sz	= 128 * 1024,
+	.num_mact_rows		= 2048,
+	.num_ports		= 10,
+	.mdio_bus_alloc		= vsc9953_mdio_bus_alloc,
+	.mdio_bus_free		= vsc9953_mdio_bus_free,
+	.pcs_init		= vsc9953_pcs_init,
+	.prevalidate_phy_mode	= vsc9953_prevalidate_phy_mode,
+};
-- 
2.25.1


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

* Re: [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization
  2020-05-27 23:41 ` [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization Vladimir Oltean
@ 2020-05-27 23:46   ` Vladimir Oltean
  0 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-27 23:46 UTC (permalink / raw)
  To: David S. Miller, Mark Brown, lkml
  Cc: netdev, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Russell King - ARM Linux admin, Antoine Tenart,
	Alexandre Belloni, Horatiu Vultur, Allan W. Nielsen,
	Microchip Linux Driver Support, Alexandru Marginean,
	Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On Thu, 28 May 2020 at 02:41, Vladimir Oltean <olteanv@gmail.com> wrote:
>
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
> Similar to the standalone regfields, add an initializer for the users
> who need to set .id_size and .id_offset in order to use the
> regmap_fields_update_bits_base API.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---

Oops, looks like I forgot to copy Mark on this patch, sorry...
Since you don't have this series in your inbox, here's the patchwork link to it:
https://patchwork.ozlabs.org/project/netdev/cover/20200527234113.2491988-1-olteanv@gmail.com/

>  include/linux/regmap.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/include/linux/regmap.h b/include/linux/regmap.h
> index 40b07168fd8e..87703d105191 100644
> --- a/include/linux/regmap.h
> +++ b/include/linux/regmap.h
> @@ -1134,6 +1134,14 @@ struct reg_field {
>                                 .msb = _msb,    \
>                                 }
>
> +#define REG_FIELD_ID(_reg, _lsb, _msb, _size, _offset) {       \
> +                               .reg = _reg,                    \
> +                               .lsb = _lsb,                    \
> +                               .msb = _msb,                    \
> +                               .id_size = _size,               \
> +                               .id_offset = _offset,           \
> +                               }
> +
>  struct regmap_field *regmap_field_alloc(struct regmap *regmap,
>                 struct reg_field reg_field);
>  void regmap_field_free(struct regmap_field *field);
> --
> 2.25.1
>

Regards,
-Vladimir

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

* Re: [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit
  2020-05-27 23:41 ` [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit Vladimir Oltean
@ 2020-05-28 14:50   ` Andrew Lunn
  2020-05-29 19:31     ` Vladimir Oltean
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew Lunn @ 2020-05-28 14:50 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, netdev, vivien.didelot, f.fainelli, linux, antoine.tenart,
	alexandre.belloni, horatiu.vultur, allan.nielsen, UNGLinuxDriver,
	alexandru.marginean, claudiu.manoil, madalin.bucur,
	radu-andrei.bulie, fido_max

On Thu, May 28, 2020 at 02:41:08AM +0300, Vladimir Oltean wrote:
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> 
> With this patch we try to kill 2 birds with 1 stone.
> 
> First of all, some switches that use tag_ocelot.c don't have the exact
> same bitfield layout for the DSA tags. The destination ports field is
> different for Seville VSC9953 for example. So the choices are to either
> duplicate tag_ocelot.c into a new tag_seville.c (sub-optimal) or somehow
> take into account a supposed ocelot->dest_ports_offset when packing this
> field into the DSA injection header (again not ideal).
> 
> Secondly, tag_ocelot.c already needs to memset a 128-bit area to zero
> and call some packing() functions of dubious performance in the
> fastpath. And most of the values it needs to pack are pretty much
> constant (BYPASS=1, SRC_PORT=CPU, DEST=port index). So it would be good
> if we could improve that.
> 
> The proposed solution is to allocate a memory area per port at probe
> time, initialize that with the statically defined bits as per chip
> hardware revision, and just perform a simpler memcpy in the fastpath.

Hi Vladimir

We try to keep the taggers independent of the DSA drivers. I think
tag_ocelot.c is the only one that breaks this.

tag drivers are kernel modules. They have all the options of a kernel
module, such as init and exit functions. You could create these
templates in the module init function, and clean them up in the exit
function. You can also register multiple taggers in one
driver. tag_brcm.c does this as an example. So you can have a Seville
tagger which uses different templates to ocelot.

       Andrew

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

* Re: [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port
  2020-05-27 23:41 ` [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port Vladimir Oltean
@ 2020-05-28 16:21   ` Jakub Kicinski
  2020-05-28 16:35     ` Vladimir Oltean
  0 siblings, 1 reply; 31+ messages in thread
From: Jakub Kicinski @ 2020-05-28 16:21 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

On Thu, 28 May 2020 02:41:04 +0300 Vladimir Oltean wrote:
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> 
> This is not being used by any other module except ocelot (i.e. felix
> does not use it). So remove the EXPORT_SYMBOL.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/ethernet/mscc/ocelot.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
> index e621c4c3ee86..ff875c2f1d46 100644
> --- a/drivers/net/ethernet/mscc/ocelot.c
> +++ b/drivers/net/ethernet/mscc/ocelot.c
> @@ -2152,7 +2152,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
>  
>  	return err;
>  }
> -EXPORT_SYMBOL(ocelot_probe_port);
>  
>  /* Configure and enable the CPU port module, which is a set of queues.
>   * If @npi contains a valid port index, the CPU port module is connected

Strangely I get an error after this patch:

ERROR: modpost: "ocelot_probe_port"
[drivers/net/ethernet/mscc/ocelot_board.ko] undefined! make[2]: ***
[__modpost] Error 1 make[1]: *** [modules] Error 2
make: *** [sub-make] Error 2

Maybe a build system error, could you double check?

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-27 23:41 ` [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch Vladimir Oltean
@ 2020-05-28 16:21   ` Jakub Kicinski
  2020-05-28 16:51     ` Vladimir Oltean
  2020-05-28 21:56   ` Andrew Lunn
  1 sibling, 1 reply; 31+ messages in thread
From: Jakub Kicinski @ 2020-05-28 16:21 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, netdev, andrew, vivien.didelot, f.fainelli, linux,
	antoine.tenart, alexandre.belloni, horatiu.vultur, allan.nielsen,
	UNGLinuxDriver, alexandru.marginean, claudiu.manoil,
	madalin.bucur, radu-andrei.bulie, fido_max

On Thu, 28 May 2020 02:41:13 +0300 Vladimir Oltean wrote:
> From: Maxim Kochetkov <fido_max@inbox.ru>
> 
> This is a 10-port (8 external, 2 internal) switch from
> Vitesse/Microsemi/Microchip that is integrated into the Freescale/NXP
> T1040 PowerPC SoC. The situation is very similar to Felix from NXP
> LS1028A, except that this is a platform device and Felix is a PCI
> device.
> 
> Extending the Felix driver to probe a PCI as well as a platform device
> would have introduced unnecessary complexity. The 'meat' of both drivers
> is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
> duplicate the Felix driver, s/Felix/Seville/, and define the low-level
> bits in seville_vsc9953.c.
> 
> Like Felix, this driver configures its own PCS on the internal MDIO bus
> using a phy_device abstraction for it (yes, it will be refactored to use
> a raw mdio_device, like other phylink drivers do, but let's keep it like
> that for now). But unlike Felix, the MDIO bus and the PCS are not from
> the same vendor. The PCS is the same QorIQ/Layerscape PCS as found in
> Felix/ENETC/DPAA*, but the internal MDIO bus that is used to access it
> is actually an instantiation of drivers/net/phy/mdio-mscc-miim.c. But it
> would be difficult to reuse that driver (it doesn't even use regmap, and
> it's less than 200 lines of code), so we hand-roll here some internal
> MDIO bus accessors within seville_vsc9953.c, which serves the purpose of
> driving the PCS absolutely fine.
> 
> Also, same as Felix, the PCS doesn't support dynamic reconfiguration of
> SerDes protocol, so we need to do pre-validation of PHY mode from device
> tree and not let phylink change it.
> 
> Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

drivers/net/dsa/ocelot/seville_vsc9953.c:636:19: warning: symbol 'vsc9953_vcap_is2_keys' was not declared. Should it be static?
drivers/net/dsa/ocelot/seville_vsc9953.c:706:19: warning: symbol 'vsc9953_vcap_is2_actions' was not declared. Should it be static?

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

* Re: [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port
  2020-05-28 16:21   ` Jakub Kicinski
@ 2020-05-28 16:35     ` Vladimir Oltean
  0 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-28 16:35 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: David S. Miller, netdev, Andrew Lunn, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Alexandre Belloni, Horatiu Vultur, Allan W. Nielsen,
	Microchip Linux Driver Support, Alexandru Marginean,
	Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On Thu, 28 May 2020 at 19:21, Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Thu, 28 May 2020 02:41:04 +0300 Vladimir Oltean wrote:
> > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >
> > This is not being used by any other module except ocelot (i.e. felix
> > does not use it). So remove the EXPORT_SYMBOL.
> >
> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > ---
> >  drivers/net/ethernet/mscc/ocelot.c | 1 -
> >  1 file changed, 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
> > index e621c4c3ee86..ff875c2f1d46 100644
> > --- a/drivers/net/ethernet/mscc/ocelot.c
> > +++ b/drivers/net/ethernet/mscc/ocelot.c
> > @@ -2152,7 +2152,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
> >
> >       return err;
> >  }
> > -EXPORT_SYMBOL(ocelot_probe_port);
> >
> >  /* Configure and enable the CPU port module, which is a set of queues.
> >   * If @npi contains a valid port index, the CPU port module is connected
>
> Strangely I get an error after this patch:
>
> ERROR: modpost: "ocelot_probe_port"
> [drivers/net/ethernet/mscc/ocelot_board.ko] undefined! make[2]: ***
> [__modpost] Error 1 make[1]: *** [modules] Error 2
> make: *** [sub-make] Error 2
>
> Maybe a build system error, could you double check?

Oh, I keep forgetting that CONFIG_MSCC_OCELOT_SWITCH and
CONFIG_MSCC_OCELOT_SWITCH_OCELOT are different modules....
Ok, so moving ocelot_probe_port to ocelot_board.c needs a bit more
work, I guess I'll just skip this patch for now.

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-28 16:21   ` Jakub Kicinski
@ 2020-05-28 16:51     ` Vladimir Oltean
  0 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-28 16:51 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: David S. Miller, netdev, Andrew Lunn, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Alexandre Belloni, Horatiu Vultur, Allan W. Nielsen,
	Microchip Linux Driver Support, Alexandru Marginean,
	Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On Thu, 28 May 2020 at 19:21, Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Thu, 28 May 2020 02:41:13 +0300 Vladimir Oltean wrote:
> > From: Maxim Kochetkov <fido_max@inbox.ru>
> >
> > This is a 10-port (8 external, 2 internal) switch from
> > Vitesse/Microsemi/Microchip that is integrated into the Freescale/NXP
> > T1040 PowerPC SoC. The situation is very similar to Felix from NXP
> > LS1028A, except that this is a platform device and Felix is a PCI
> > device.
> >
> > Extending the Felix driver to probe a PCI as well as a platform device
> > would have introduced unnecessary complexity. The 'meat' of both drivers
> > is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
> > duplicate the Felix driver, s/Felix/Seville/, and define the low-level
> > bits in seville_vsc9953.c.
> >
> > Like Felix, this driver configures its own PCS on the internal MDIO bus
> > using a phy_device abstraction for it (yes, it will be refactored to use
> > a raw mdio_device, like other phylink drivers do, but let's keep it like
> > that for now). But unlike Felix, the MDIO bus and the PCS are not from
> > the same vendor. The PCS is the same QorIQ/Layerscape PCS as found in
> > Felix/ENETC/DPAA*, but the internal MDIO bus that is used to access it
> > is actually an instantiation of drivers/net/phy/mdio-mscc-miim.c. But it
> > would be difficult to reuse that driver (it doesn't even use regmap, and
> > it's less than 200 lines of code), so we hand-roll here some internal
> > MDIO bus accessors within seville_vsc9953.c, which serves the purpose of
> > driving the PCS absolutely fine.
> >
> > Also, same as Felix, the PCS doesn't support dynamic reconfiguration of
> > SerDes protocol, so we need to do pre-validation of PHY mode from device
> > tree and not let phylink change it.
> >
> > Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>
> drivers/net/dsa/ocelot/seville_vsc9953.c:636:19: warning: symbol 'vsc9953_vcap_is2_keys' was not declared. Should it be static?
> drivers/net/dsa/ocelot/seville_vsc9953.c:706:19: warning: symbol 'vsc9953_vcap_is2_actions' was not declared. Should it be static?

Rhetorical question...

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-27 23:41 ` [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch Vladimir Oltean
  2020-05-28 16:21   ` Jakub Kicinski
@ 2020-05-28 21:56   ` Andrew Lunn
  2020-05-28 22:09     ` Vladimir Oltean
  1 sibling, 1 reply; 31+ messages in thread
From: Andrew Lunn @ 2020-05-28 21:56 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, netdev, vivien.didelot, f.fainelli, linux, antoine.tenart,
	alexandre.belloni, horatiu.vultur, allan.nielsen, UNGLinuxDriver,
	alexandru.marginean, claudiu.manoil, madalin.bucur,
	radu-andrei.bulie, fido_max

> Extending the Felix driver to probe a PCI as well as a platform device
> would have introduced unnecessary complexity. The 'meat' of both drivers
> is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
> duplicate the Felix driver, s/Felix/Seville/, and define the low-level
> bits in seville_vsc9953.c.

Hi Vladimir

That has resulted in a lot of duplicated code.

Is there an overall family name for these switch?

Could you add foo_set_ageing_time() with both felix and saville share?

      Andrew

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-28 21:56   ` Andrew Lunn
@ 2020-05-28 22:09     ` Vladimir Oltean
  2020-05-29  8:14       ` Alexandre Belloni
  0 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-28 22:09 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: David S. Miller, netdev, Vivien Didelot, Florian Fainelli,
	Russell King - ARM Linux admin, Antoine Tenart,
	Alexandre Belloni, Horatiu Vultur, Allan W. Nielsen,
	Microchip Linux Driver Support, Alexandru Marginean,
	Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On Fri, 29 May 2020 at 00:56, Andrew Lunn <andrew@lunn.ch> wrote:
>
> > Extending the Felix driver to probe a PCI as well as a platform device
> > would have introduced unnecessary complexity. The 'meat' of both drivers
> > is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
> > duplicate the Felix driver, s/Felix/Seville/, and define the low-level
> > bits in seville_vsc9953.c.
>
> Hi Vladimir
>
> That has resulted in a lot of duplicated code.
>
> Is there an overall family name for these switch?
>
> Could you add foo_set_ageing_time() with both felix and saville share?
>
>       Andrew

Yes, it looks like I can. I can move Felix PCI probing to
felix_vsc9959.c, Seville platform device probing to seville_vsc9953.c,
and remove seville.c.
I would not be in a position to know whether there's any larger family
name which should be used here. According to
https://media.digikey.com/pdf/Data%20Sheets/Microsemi%20PDFs/Ocelot_Family_of_Ethernet_Switches_Dec2016.pdf,
"Ocelot is a low port count, small form factor Ethernet switch family
for the Industrial IoT market". Seville would not qualify as part of
the Ocelot family (high port count, no 1588) but that doesn't mean it
can't use the Ocelot driver. As confusing as it might be for the
people at Microchip, I would tend to call anything that probes as pure
switchdev "ocelot" and anything that probes as DSA "felix", since
these were the first 2 drivers that entered mainline. Under this
working model, Seville would reuse the struct dsa_switch_ops
felix_switch_ops, while having its own low-level seville_vsc9953.c
that deals with platform integration specific stuff (probing, internal
MDIO, register map, etc), and the felix_switch_ops would call into
ocelot for the common functionalities.
What do you think?

-Vladimir

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-28 22:09     ` Vladimir Oltean
@ 2020-05-29  8:14       ` Alexandre Belloni
  2020-05-29  8:30         ` Vladimir Oltean
  0 siblings, 1 reply; 31+ messages in thread
From: Alexandre Belloni @ 2020-05-29  8:14 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, David S. Miller, netdev, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Horatiu Vultur, Allan W. Nielsen, Microchip Linux Driver Support,
	Alexandru Marginean, Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On 29/05/2020 01:09:16+0300, Vladimir Oltean wrote:
> On Fri, 29 May 2020 at 00:56, Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > > Extending the Felix driver to probe a PCI as well as a platform device
> > > would have introduced unnecessary complexity. The 'meat' of both drivers
> > > is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
> > > duplicate the Felix driver, s/Felix/Seville/, and define the low-level
> > > bits in seville_vsc9953.c.
> >
> > Hi Vladimir
> >
> > That has resulted in a lot of duplicated code.
> >
> > Is there an overall family name for these switch?
> >
> > Could you add foo_set_ageing_time() with both felix and saville share?
> >
> >       Andrew
> 
> Yes, it looks like I can. I can move Felix PCI probing to
> felix_vsc9959.c, Seville platform device probing to seville_vsc9953.c,
> and remove seville.c.
> I would not be in a position to know whether there's any larger family
> name which should be used here. According to
> https://media.digikey.com/pdf/Data%20Sheets/Microsemi%20PDFs/Ocelot_Family_of_Ethernet_Switches_Dec2016.pdf,
> "Ocelot is a low port count, small form factor Ethernet switch family
> for the Industrial IoT market". Seville would not qualify as part of
> the Ocelot family (high port count, no 1588) but that doesn't mean it
> can't use the Ocelot driver. As confusing as it might be for the
> people at Microchip, I would tend to call anything that probes as pure
> switchdev "ocelot" and anything that probes as DSA "felix", since

As ocelot can be used in a DSA configuration (even if it is not
implemented yet), I don't think this would be correct. From my point of
view, felix and seville are part of the ocelot family.

> these were the first 2 drivers that entered mainline. Under this
> working model, Seville would reuse the struct dsa_switch_ops
> felix_switch_ops, while having its own low-level seville_vsc9953.c
> that deals with platform integration specific stuff (probing, internal
> MDIO, register map, etc), and the felix_switch_ops would call into
> ocelot for the common functionalities.
> What do you think?
> 
> -Vladimir

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

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-29  8:14       ` Alexandre Belloni
@ 2020-05-29  8:30         ` Vladimir Oltean
  2020-05-29  9:03           ` Alexandre Belloni
  0 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-29  8:30 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Andrew Lunn, David S. Miller, netdev, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Horatiu Vultur, Allan W. Nielsen, Microchip Linux Driver Support,
	Alexandru Marginean, Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

Hi Alexandre,

On Fri, 29 May 2020 at 11:14, Alexandre Belloni
<alexandre.belloni@bootlin.com> wrote:
>
> On 29/05/2020 01:09:16+0300, Vladimir Oltean wrote:
> > On Fri, 29 May 2020 at 00:56, Andrew Lunn <andrew@lunn.ch> wrote:
> > >
> > > > Extending the Felix driver to probe a PCI as well as a platform device
> > > > would have introduced unnecessary complexity. The 'meat' of both drivers
> > > > is in drivers/net/ethernet/mscc/ocelot*.c anyway, so let's just
> > > > duplicate the Felix driver, s/Felix/Seville/, and define the low-level
> > > > bits in seville_vsc9953.c.
> > >
> > > Hi Vladimir
> > >
> > > That has resulted in a lot of duplicated code.
> > >
> > > Is there an overall family name for these switch?
> > >
> > > Could you add foo_set_ageing_time() with both felix and saville share?
> > >
> > >       Andrew
> >
> > Yes, it looks like I can. I can move Felix PCI probing to
> > felix_vsc9959.c, Seville platform device probing to seville_vsc9953.c,
> > and remove seville.c.
> > I would not be in a position to know whether there's any larger family
> > name which should be used here. According to
> > https://media.digikey.com/pdf/Data%20Sheets/Microsemi%20PDFs/Ocelot_Family_of_Ethernet_Switches_Dec2016.pdf,
> > "Ocelot is a low port count, small form factor Ethernet switch family
> > for the Industrial IoT market". Seville would not qualify as part of
> > the Ocelot family (high port count, no 1588) but that doesn't mean it
> > can't use the Ocelot driver. As confusing as it might be for the
> > people at Microchip, I would tend to call anything that probes as pure
> > switchdev "ocelot" and anything that probes as DSA "felix", since
>
> As ocelot can be used in a DSA configuration (even if it is not
> implemented yet), I don't think this would be correct. From my point of
> view, felix and seville are part of the ocelot family.
>

In this case, there would be a third driver in
drivers/net/dsa/ocelot/ocelot_vsc7511.c which uses the intermediate
felix_switch_ops from felix.c to access the ocelot core
implementation. Unless you have better naming suggestions?

> > these were the first 2 drivers that entered mainline. Under this
> > working model, Seville would reuse the struct dsa_switch_ops
> > felix_switch_ops, while having its own low-level seville_vsc9953.c
> > that deals with platform integration specific stuff (probing, internal
> > MDIO, register map, etc), and the felix_switch_ops would call into
> > ocelot for the common functionalities.
> > What do you think?
> >
> > -Vladimir
>
> --
> Alexandre Belloni, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com

Thanks,
-Vladimir

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-29  8:30         ` Vladimir Oltean
@ 2020-05-29  9:03           ` Alexandre Belloni
  2020-05-29 15:42             ` Vladimir Oltean
  0 siblings, 1 reply; 31+ messages in thread
From: Alexandre Belloni @ 2020-05-29  9:03 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, David S. Miller, netdev, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Horatiu Vultur, Allan W. Nielsen, Microchip Linux Driver Support,
	Alexandru Marginean, Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On 29/05/2020 11:30:43+0300, Vladimir Oltean wrote:
> > As ocelot can be used in a DSA configuration (even if it is not
> > implemented yet), I don't think this would be correct. From my point of
> > view, felix and seville are part of the ocelot family.
> >
> 
> In this case, there would be a third driver in
> drivers/net/dsa/ocelot/ocelot_vsc7511.c which uses the intermediate
> felix_switch_ops from felix.c to access the ocelot core
> implementation. Unless you have better naming suggestions?
> 

I don't. Maybe felix.c should have been ocelot.c from the beginning but
honestly, it doesn't matter that much.

BTW, maybe we should merge the VITESSE FELIX ETHERNET SWITCH DRIVER and
MICROSEMI ETHERNET SWITCH DRIVER entries in MAINTAINERS. You do much
more work in drivers/net/ethernet/mscc/ than I currently do.

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

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-29  9:03           ` Alexandre Belloni
@ 2020-05-29 15:42             ` Vladimir Oltean
  2020-05-29 17:20               ` Alexandre Belloni
  0 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-29 15:42 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Andrew Lunn, David S. Miller, netdev, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Horatiu Vultur, Allan W. Nielsen, Microchip Linux Driver Support,
	Alexandru Marginean, Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On Fri, 29 May 2020 at 12:03, Alexandre Belloni
<alexandre.belloni@bootlin.com> wrote:
>
> On 29/05/2020 11:30:43+0300, Vladimir Oltean wrote:
> > > As ocelot can be used in a DSA configuration (even if it is not
> > > implemented yet), I don't think this would be correct. From my point of
> > > view, felix and seville are part of the ocelot family.
> > >
> >
> > In this case, there would be a third driver in
> > drivers/net/dsa/ocelot/ocelot_vsc7511.c which uses the intermediate
> > felix_switch_ops from felix.c to access the ocelot core
> > implementation. Unless you have better naming suggestions?
> >
>
> I don't. Maybe felix.c should have been ocelot.c from the beginning but
> honestly, it doesn't matter that much.
>

Technically Seville is not part of the Ocelot family but part of
Serval, but then again, it's just a marketing name, so it doesn't
really mean anything..
I am a bit reluctant to rename the DSA driver ops to "ocelot", since
it would be even more confusing for everyone to have a function
ocelot_dsa_set_ageing_time that calls ocelot_set_ageing_time. At least
this way, there's going to be some learning curve figuring out that
felix is an umbrella term for DSA ops, but there will be more naming
predictability. (at least that's how I see it)

> BTW, maybe we should merge the VITESSE FELIX ETHERNET SWITCH DRIVER and
> MICROSEMI ETHERNET SWITCH DRIVER entries in MAINTAINERS. You do much
> more work in drivers/net/ethernet/mscc/ than I currently do.
>

How would you see the merged MAINTAINERS entry? Something like this?

MICROSEMI ETHERNET SWITCH DRIVER
M:    Alexandre Belloni <alexandre.belloni@bootlin.com>
M:    Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
M:    Vladimir Oltean <vladimir.oltean@nxp.com>
M:    Claudiu Manoil <claudiu.manoil@nxp.com>
L:    netdev@vger.kernel.org
S:    Maintained
F:    include/soc/mscc/ocelot*
F:    drivers/net/ethernet/mscc/
F:    drivers/net/dsa/ocelot/*
F:    net/dsa/tag_ocelot.c

Any takers from Microchip, or is the internal mailing list enough?

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

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

* Re: [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch
  2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
                   ` (10 preceding siblings ...)
  2020-05-27 23:41 ` [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch Vladimir Oltean
@ 2020-05-29 16:51 ` Mark Brown
  2020-05-29 16:59   ` Mark Brown
  11 siblings, 1 reply; 31+ messages in thread
From: Mark Brown @ 2020-05-29 16:51 UTC (permalink / raw)
  To: Vladimir Oltean, davem
  Cc: linux, claudiu.manoil, vivien.didelot, f.fainelli, andrew,
	allan.nielsen, antoine.tenart, netdev, fido_max,
	alexandre.belloni, radu-andrei.bulie, horatiu.vultur,
	alexandru.marginean, UNGLinuxDriver, madalin.bucur

On Thu, 28 May 2020 02:41:02 +0300, Vladimir Oltean wrote:
> Looking at the Felix and Ocelot drivers, Maxim asked if it would be
> possible to use them as a base for a new driver for the switch inside
> NXP T1040. Turns out, it is! The result is a driver eerily similar to
> Felix.
> 
> The biggest challenge seems to be getting register read/write API
> generic enough to cover such wild bitfield variations between hardware
> generations. There is a patch on the regmap core which I would like to
> get in through the networking subsystem, if possible (and if Mark is
> ok), since it's a trivial addition.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-next

Thanks!

[1/1] regmap: add helper for per-port regfield initialization
      commit: 8baebfc2aca26e3fa67ab28343671b82be42b22c

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

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

* Re: [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch
  2020-05-29 16:51 ` [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Mark Brown
@ 2020-05-29 16:59   ` Mark Brown
  2020-05-29 17:28     ` Vladimir Oltean
  0 siblings, 1 reply; 31+ messages in thread
From: Mark Brown @ 2020-05-29 16:59 UTC (permalink / raw)
  To: Vladimir Oltean, davem
  Cc: linux, claudiu.manoil, vivien.didelot, f.fainelli, andrew,
	allan.nielsen, antoine.tenart, netdev, fido_max,
	alexandre.belloni, radu-andrei.bulie, horatiu.vultur,
	alexandru.marginean, UNGLinuxDriver, madalin.bucur

[-- Attachment #1: Type: text/plain, Size: 315 bytes --]

On Fri, May 29, 2020 at 05:51:52PM +0100, Mark Brown wrote:

> [1/1] regmap: add helper for per-port regfield initialization
>       commit: 8baebfc2aca26e3fa67ab28343671b82be42b22c

Let me know if you need a pull request for this, I figured it was too
late to deal with the cross tree issues for the merge window.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch
  2020-05-29 15:42             ` Vladimir Oltean
@ 2020-05-29 17:20               ` Alexandre Belloni
  0 siblings, 0 replies; 31+ messages in thread
From: Alexandre Belloni @ 2020-05-29 17:20 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, David S. Miller, netdev, Vivien Didelot,
	Florian Fainelli, Russell King - ARM Linux admin, Antoine Tenart,
	Horatiu Vultur, Allan W. Nielsen, Microchip Linux Driver Support,
	Alexandru Marginean, Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

On 29/05/2020 18:42:47+0300, Vladimir Oltean wrote:
> On Fri, 29 May 2020 at 12:03, Alexandre Belloni
> <alexandre.belloni@bootlin.com> wrote:
> >
> > On 29/05/2020 11:30:43+0300, Vladimir Oltean wrote:
> > > > As ocelot can be used in a DSA configuration (even if it is not
> > > > implemented yet), I don't think this would be correct. From my point of
> > > > view, felix and seville are part of the ocelot family.
> > > >
> > >
> > > In this case, there would be a third driver in
> > > drivers/net/dsa/ocelot/ocelot_vsc7511.c which uses the intermediate
> > > felix_switch_ops from felix.c to access the ocelot core
> > > implementation. Unless you have better naming suggestions?
> > >
> >
> > I don't. Maybe felix.c should have been ocelot.c from the beginning but
> > honestly, it doesn't matter that much.
> >
> 
> Technically Seville is not part of the Ocelot family but part of
> Serval, but then again, it's just a marketing name, so it doesn't
> really mean anything..

When I submitted ocelot, I was thinking we would have different drivers
for jaguar, luton, ocelot, serval and serval-t. IIRC, ocelot is a subset
of serval or at least, it is similar enough to share the same driver.

> I am a bit reluctant to rename the DSA driver ops to "ocelot", since
> it would be even more confusing for everyone to have a function
> ocelot_dsa_set_ageing_time that calls ocelot_set_ageing_time. At least
> this way, there's going to be some learning curve figuring out that
> felix is an umbrella term for DSA ops, but there will be more naming
> predictability. (at least that's how I see it)
> 

I'm fine with the current naming, I was certainly not suggesting to
change it.

> > BTW, maybe we should merge the VITESSE FELIX ETHERNET SWITCH DRIVER and
> > MICROSEMI ETHERNET SWITCH DRIVER entries in MAINTAINERS. You do much
> > more work in drivers/net/ethernet/mscc/ than I currently do.
> >
> 
> How would you see the merged MAINTAINERS entry? Something like this?
> 
> MICROSEMI ETHERNET SWITCH DRIVER
> M:    Alexandre Belloni <alexandre.belloni@bootlin.com>
> M:    Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
> M:    Vladimir Oltean <vladimir.oltean@nxp.com>

You should probably be in the top position.

> M:    Claudiu Manoil <claudiu.manoil@nxp.com>
> L:    netdev@vger.kernel.org
> S:    Maintained

I guess this could stay Supported unless you are not paid to work on
that.

> F:    include/soc/mscc/ocelot*
> F:    drivers/net/ethernet/mscc/
> F:    drivers/net/dsa/ocelot/*
> F:    net/dsa/tag_ocelot.c
> 
> Any takers from Microchip, or is the internal mailing list enough?

It seems ok for now, we can always add/replace people later on.

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

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

* Re: [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch
  2020-05-29 16:59   ` Mark Brown
@ 2020-05-29 17:28     ` Vladimir Oltean
  2020-05-29 17:34       ` Mark Brown
  0 siblings, 1 reply; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-29 17:28 UTC (permalink / raw)
  To: Mark Brown
  Cc: David S. Miller, Russell King - ARM Linux admin, Claudiu Manoil,
	Vivien Didelot, Florian Fainelli, Andrew Lunn, Allan W. Nielsen,
	Antoine Tenart, netdev, fido_max, Alexandre Belloni,
	radu-andrei.bulie, Horatiu Vultur, Alexandru Marginean,
	Microchip Linux Driver Support, Madalin Bucur (OSS)

Hi Mark,

On Fri, 29 May 2020 at 19:59, Mark Brown <broonie@kernel.org> wrote:
>
> On Fri, May 29, 2020 at 05:51:52PM +0100, Mark Brown wrote:
>
> > [1/1] regmap: add helper for per-port regfield initialization
> >       commit: 8baebfc2aca26e3fa67ab28343671b82be42b22c
>
> Let me know if you need a pull request for this, I figured it was too
> late to deal with the cross tree issues for the merge window.

Thanks a lot for merging this. I plan to resend this series again (on
the last mile!) during the weekend, with the feedback collected so
far, so I'm not sure what is the best path to make sure Dave also has
this patch in his tree so I don't break net-next.

-Vladimir

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

* Re: [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch
  2020-05-29 17:28     ` Vladimir Oltean
@ 2020-05-29 17:34       ` Mark Brown
  2020-05-29 17:49         ` Vladimir Oltean
  0 siblings, 1 reply; 31+ messages in thread
From: Mark Brown @ 2020-05-29 17:34 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: David S. Miller, Russell King - ARM Linux admin, Claudiu Manoil,
	Vivien Didelot, Florian Fainelli, Andrew Lunn, Allan W. Nielsen,
	Antoine Tenart, netdev, fido_max, Alexandre Belloni,
	radu-andrei.bulie, Horatiu Vultur, Alexandru Marginean,
	Microchip Linux Driver Support, Madalin Bucur (OSS)

[-- Attachment #1: Type: text/plain, Size: 618 bytes --]

On Fri, May 29, 2020 at 08:28:01PM +0300, Vladimir Oltean wrote:

> Thanks a lot for merging this. I plan to resend this series again (on
> the last mile!) during the weekend, with the feedback collected so
> far, so I'm not sure what is the best path to make sure Dave also has
> this patch in his tree so I don't break net-next.

That was what the pull request would be for, though if you need to
resend the chances are it'll be after the merge window before it gets
applied in which case he'll get the patch through Linus' tree which
makes things easier (that was part of the reason I just went ahead and
applied).

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch
  2020-05-29 17:34       ` Mark Brown
@ 2020-05-29 17:49         ` Vladimir Oltean
  0 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-29 17:49 UTC (permalink / raw)
  To: Mark Brown
  Cc: David S. Miller, Russell King - ARM Linux admin, Claudiu Manoil,
	Vivien Didelot, Florian Fainelli, Andrew Lunn, Allan W. Nielsen,
	Antoine Tenart, netdev, fido_max, Alexandre Belloni,
	radu-andrei.bulie, Horatiu Vultur, Alexandru Marginean,
	Microchip Linux Driver Support, Madalin Bucur (OSS)

On Fri, 29 May 2020 at 20:34, Mark Brown <broonie@kernel.org> wrote:
>
> On Fri, May 29, 2020 at 08:28:01PM +0300, Vladimir Oltean wrote:
>
> > Thanks a lot for merging this. I plan to resend this series again (on
> > the last mile!) during the weekend, with the feedback collected so
> > far, so I'm not sure what is the best path to make sure Dave also has
> > this patch in his tree so I don't break net-next.
>
> That was what the pull request would be for, though if you need to
> resend the chances are it'll be after the merge window before it gets
> applied in which case he'll get the patch through Linus' tree which
> makes things easier (that was part of the reason I just went ahead and
> applied).

Yeah, well, I was hoping I could get this in for 5.8, since the
changes requested so far aren't radical (and neither are the patches
themselves). If it's too much of a hassle I can wait for the merge
window to close, sure.

Thanks,
-Vladimir

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

* Re: [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit
  2020-05-28 14:50   ` Andrew Lunn
@ 2020-05-29 19:31     ` Vladimir Oltean
  0 siblings, 0 replies; 31+ messages in thread
From: Vladimir Oltean @ 2020-05-29 19:31 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: David S. Miller, netdev, Vivien Didelot, Florian Fainelli,
	Russell King - ARM Linux admin, Antoine Tenart,
	Alexandre Belloni, Horatiu Vultur, Allan W. Nielsen,
	Microchip Linux Driver Support, Alexandru Marginean,
	Claudiu Manoil, Madalin Bucur (OSS),
	radu-andrei.bulie, fido_max

Hi Andrew,

On Thu, 28 May 2020 at 17:51, Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Thu, May 28, 2020 at 02:41:08AM +0300, Vladimir Oltean wrote:
> > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >
> > With this patch we try to kill 2 birds with 1 stone.
> >
> > First of all, some switches that use tag_ocelot.c don't have the exact
> > same bitfield layout for the DSA tags. The destination ports field is
> > different for Seville VSC9953 for example. So the choices are to either
> > duplicate tag_ocelot.c into a new tag_seville.c (sub-optimal) or somehow
> > take into account a supposed ocelot->dest_ports_offset when packing this
> > field into the DSA injection header (again not ideal).
> >
> > Secondly, tag_ocelot.c already needs to memset a 128-bit area to zero
> > and call some packing() functions of dubious performance in the
> > fastpath. And most of the values it needs to pack are pretty much
> > constant (BYPASS=1, SRC_PORT=CPU, DEST=port index). So it would be good
> > if we could improve that.
> >
> > The proposed solution is to allocate a memory area per port at probe
> > time, initialize that with the statically defined bits as per chip
> > hardware revision, and just perform a simpler memcpy in the fastpath.
>
> Hi Vladimir
>
> We try to keep the taggers independent of the DSA drivers. I think
> tag_ocelot.c is the only one that breaks this.
>
> tag drivers are kernel modules. They have all the options of a kernel
> module, such as init and exit functions. You could create these
> templates in the module init function, and clean them up in the exit
> function. You can also register multiple taggers in one
> driver. tag_brcm.c does this as an example. So you can have a Seville
> tagger which uses different templates to ocelot.
>
>        Andrew

I don't particularly like that tag_brcm.c is riddled with #if /
#endif, they make it difficult to follow.

And if I allocate/free the xmit template in the
dsa_tag_driver_module_init / dsa_tag_driver_module_exit, how can I
reach the pointer to the correct per-switch-per-port template in the
ocelot_xmit function?

Please note that ocelot_xmit is already stateful, and it _needs_ to be
stateful: for 1588, it saves and increments the TX timestamp ID which
will be matched to the data that is received in felix_irq_handler.

And sja1105 also breaks the tagger/driver separation, and in even
"worse" ways - see sja1105_xmit_tpid which transmits a different frame
depending on which state the driver is in; also sja1105_decode_subvlan
which on RX looks up a table populated by the driver.

Generally speaking, I don't see any good reason why keeping the tagger
and the driver separated should be a design goal, especially when the
hotpath depends on stateful information (and the tagging driver can't
do anything at all without a backing switch driver anyway). Separation
could be done only in the simplest of cases, but as more advanced
features are necessary (not arguing that the template I'm adding here
is "advanced" stuff), this becomes practically impossible. Please also
see this tag_ocelot.c patch which needs to take the classified VLAN
from the DSA tag, or not, depending on the VLAN awareness state of the
port:
https://patchwork.ozlabs.org/project/netdev/patch/20200506074900.28529-7-xiaoliang.yang_1@nxp.com/

Thanks,
-Vladimir

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

end of thread, other threads:[~2020-05-29 19:31 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-27 23:41 [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 01/11] regmap: add helper for per-port regfield initialization Vladimir Oltean
2020-05-27 23:46   ` Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 02/11] net: mscc: ocelot: unexport ocelot_probe_port Vladimir Oltean
2020-05-28 16:21   ` Jakub Kicinski
2020-05-28 16:35     ` Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 03/11] net: mscc: ocelot: convert port registers to regmap Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 04/11] soc/mscc: ocelot: add MII registers description Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 05/11] net: mscc: ocelot: convert QSYS_SWITCH_PORT_MODE and SYS_PORT_MODE to regfields Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 06/11] net: dsa: ocelot: create a template for the DSA tags on xmit Vladimir Oltean
2020-05-28 14:50   ` Andrew Lunn
2020-05-29 19:31     ` Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 07/11] net: mscc: ocelot: split writes to pause frame enable bit and to thresholds Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 08/11] net: mscc: ocelot: disable flow control on NPI interface Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 09/11] net: mscc: ocelot: convert SYS_PAUSE_CFG register access to regfield Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 10/11] net: mscc: ocelot: extend watermark encoding function Vladimir Oltean
2020-05-27 23:41 ` [PATCH net-next 11/11] net: dsa: ocelot: introduce driver for Seville VSC9953 switch Vladimir Oltean
2020-05-28 16:21   ` Jakub Kicinski
2020-05-28 16:51     ` Vladimir Oltean
2020-05-28 21:56   ` Andrew Lunn
2020-05-28 22:09     ` Vladimir Oltean
2020-05-29  8:14       ` Alexandre Belloni
2020-05-29  8:30         ` Vladimir Oltean
2020-05-29  9:03           ` Alexandre Belloni
2020-05-29 15:42             ` Vladimir Oltean
2020-05-29 17:20               ` Alexandre Belloni
2020-05-29 16:51 ` [PATCH net-next 00/11] New DSA driver for VSC9953 Seville switch Mark Brown
2020-05-29 16:59   ` Mark Brown
2020-05-29 17:28     ` Vladimir Oltean
2020-05-29 17:34       ` Mark Brown
2020-05-29 17:49         ` Vladimir Oltean

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.