git: 9b2a503a1179 - main - e6000sw: add support for 88E6190X

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Sun, 27 Apr 2025 18:38:12 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=9b2a503a1179e026a4efc0b2e0a910168bc806ed

commit 9b2a503a1179e026a4efc0b2e0a910168bc806ed
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2025-04-24 17:32:15 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2025-04-27 18:11:26 +0000

    e6000sw: add support for 88E6190X
    
    This adds the minimum support required to probe/attach the 88E6190X.
    
    I've tested this against an AT&T ATT-150 OCP device (Silicom i3000)
    with local changes to export MDIO via ixge(4).
    
    Hints are required to probe/attach/configure the switch on amd64,
    but with the mentioned diffs, it does work.
    
    Thanks to Stas Alekseev <stas@alekseev.us> for the pull request
    and Stas / Jason Hensler <omegadraconis@gmail.com> for chasing
    down information about the chipset, linux stuff and AT&T OCP
    hardware information.
    
    PR:             kern/281211
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1408
    Differential Revision:  https://reviews.freebsd.org/D50044
    Reviewed by:    imp
---
 sys/dev/etherswitch/e6000sw/e6000sw.c    | 33 +++++++++++++++++++++++++-------
 sys/dev/etherswitch/e6000sw/e6000swreg.h |  9 +++++----
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/sys/dev/etherswitch/e6000sw/e6000sw.c b/sys/dev/etherswitch/e6000sw/e6000sw.c
index 19d8e85decf6..0041119ca300 100644
--- a/sys/dev/etherswitch/e6000sw/e6000sw.c
+++ b/sys/dev/etherswitch/e6000sw/e6000sw.c
@@ -217,7 +217,8 @@ e6000sw_probe(device_t dev)
 #ifdef FDT
 	phandle_t switch_node;
 #else
-	int is_6190;
+	int is_6190 = 0;
+	int is_6190x = 0;
 #endif
 
 	sc = device_get_softc(dev);
@@ -253,15 +254,25 @@ e6000sw_probe(device_t dev)
 	    device_get_unit(sc->dev), "addr", &sc->sw_addr) != 0)
 		return (ENXIO);
 	if (resource_int_value(device_get_name(sc->dev),
-	    device_get_unit(sc->dev), "is6190", &is_6190) != 0)
+	    device_get_unit(sc->dev), "is6190", &is_6190) != 0) {
 		/*
 		 * Check "is8190" to keep backward compatibility with
 		 * older setups.
 		 */
 		resource_int_value(device_get_name(sc->dev),
 		    device_get_unit(sc->dev), "is8190", &is_6190);
+	}
+	resource_int_value(device_get_name(sc->dev),
+	    device_get_unit(sc->dev), "is6190x", &is_6190x);
+		if (is_6190 != 0 && is_6190x != 0) {
+			device_printf(dev,
+			    "Cannot configure conflicting variants (6190 / 6190x)\n");
+			return (ENXIO);
+		}
 	if (is_6190 != 0)
 		sc->swid = MV88E6190;
+	else if (is_6190x != 0)
+		sc->swid = MV88E6190X;
 #endif
 	if (sc->sw_addr < 0 || sc->sw_addr > 32)
 		return (ENXIO);
@@ -303,6 +314,10 @@ e6000sw_probe(device_t dev)
 		description = "Marvell 88E6190";
 		sc->num_ports = 11;
 		break;
+	case MV88E6190X:
+		description = "Marvell 88E6190X";
+		sc->num_ports = 11;
+		break;
 	default:
 		device_printf(dev, "Unrecognized device, id 0x%x.\n", sc->swid);
 		return (ENXIO);
@@ -333,7 +348,7 @@ e6000sw_parse_fixed_link(e6000sw_softc_t *sc, phandle_t node, uint32_t port)
 			return (ENXIO);
 		}
 		if (speed == 2500 && (MVSWITCH(sc, MV88E6141) ||
-		     MVSWITCH(sc, MV88E6341) || MVSWITCH(sc, MV88E6190)))
+		     MVSWITCH(sc, MV88E6341) || MVSWITCH(sc, MV88E6190) || MVSWITCH(sc, MV88E6190X)))
 			sc->fixed25_mask |= (1 << port);
 	}
 
@@ -597,22 +612,26 @@ e6000sw_attach(device_t dev)
 				reg |= PSC_CONTROL_SPD2500;
 			else
 				reg |= PSC_CONTROL_SPD1000;
-			if (MVSWITCH(sc, MV88E6190) &&
+			if ((MVSWITCH(sc, MV88E6190) ||
+			    MVSWITCH(sc, MV88E6190X)) &&
 			    e6000sw_is_fixed25port(sc, port))
 				reg |= PSC_CONTROL_ALT_SPD;
 			reg |= PSC_CONTROL_FORCED_DPX | PSC_CONTROL_FULLDPX |
 			    PSC_CONTROL_FORCED_LINK | PSC_CONTROL_LINK_UP |
 			    PSC_CONTROL_FORCED_SPD;
-			if (!MVSWITCH(sc, MV88E6190))
+			if (!MVSWITCH(sc, MV88E6190) &&
+			    !MVSWITCH(sc, MV88E6190X))
 				reg |= PSC_CONTROL_FORCED_FC | PSC_CONTROL_FC_ON;
 			if (MVSWITCH(sc, MV88E6141) ||
 			    MVSWITCH(sc, MV88E6341) ||
-			    MVSWITCH(sc, MV88E6190))
+			    MVSWITCH(sc, MV88E6190) ||
+			    MVSWITCH(sc, MV88E6190X))
 				reg |= PSC_CONTROL_FORCED_EEE;
 			e6000sw_writereg(sc, REG_PORT(sc, port), PSC_CONTROL,
 			    reg);
 			/* Power on the SERDES interfaces. */
-			if (MVSWITCH(sc, MV88E6190) &&
+			if ((MVSWITCH(sc, MV88E6190) ||
+			    MVSWITCH(sc, MV88E6190X)) &&
 			    (port == 9 || port == 10)) {
 				if (e6000sw_is_fixed25port(sc, port))
 					sgmii = false;
diff --git a/sys/dev/etherswitch/e6000sw/e6000swreg.h b/sys/dev/etherswitch/e6000sw/e6000swreg.h
index 7c952052a401..ec4503faeec5 100644
--- a/sys/dev/etherswitch/e6000sw/e6000swreg.h
+++ b/sys/dev/etherswitch/e6000sw/e6000swreg.h
@@ -47,6 +47,7 @@ struct atu_opt {
 #define	MV88E6172	0x1720
 #define	MV88E6176	0x1760
 #define	MV88E6190	0x1900
+#define	MV88E6190X	0x0a00
 
 #define	MVSWITCH(_sc, id)	((_sc)->swid == (id))
 #define	MVSWITCH_MULTICHIP(_sc)	((_sc)->sw_addr != 0)
@@ -56,7 +57,7 @@ struct atu_opt {
  */
 #define	REG_GLOBAL			0x1b
 #define	REG_GLOBAL2			0x1c
-#define	REG_PORT(_sc, p)		((MVSWITCH((_sc), MV88E6190) ? 0 : 0x10) + (p))
+#define	REG_PORT(_sc, p)		(((MVSWITCH((_sc), MV88E6190) || MVSWITCH((_sc), MV88E6190X)) ? 0 : 0x10) + (p))
 
 #define	REG_NUM_MAX			31
 
@@ -138,13 +139,13 @@ struct atu_opt {
 #define	VTU_DATA			7
 #define	VTU_DATA2			8
 
-#define	VTU_FID_MASK(_sc)		(MVSWITCH((_sc), MV88E6190) ? 0xfff : 0xff)
+#define	VTU_FID_MASK(_sc)		((MVSWITCH((_sc), MV88E6190) || MVSWITCH((_sc), MV88E6190X)) ? 0xfff : 0xff)
 #define	VTU_FID_POLICY			(1 << 12)
 #define	VTU_PORT_UNMODIFIED		0
 #define	VTU_PORT_UNTAGGED		1
 #define	VTU_PORT_TAGGED			2
 #define	VTU_PORT_DISCARD		3
-#define	VTU_PPREG(_sc)			(MVSWITCH((_sc), MV88E6190) ? 8 : 4)
+#define	VTU_PPREG(_sc)			((MVSWITCH((_sc), MV88E6190) || MVSWITCH((_sc), MV88E6190X)) ? 8 : 4)
 #define	VTU_PORT(_sc, p)		(((p) % VTU_PPREG(_sc)) * (16 / VTU_PPREG(_sc)))
 #define	VTU_PORT_MASK			3
 #define	VTU_BUSY			(1 << 15)
@@ -174,7 +175,7 @@ struct atu_opt {
 #define	ATU_MAC_ADDR45			15
 
 #define	ATU_DATA_LAG                    (1 << 15)
-#define	ATU_PORT_MASK(_sc)		(MVSWITCH((_sc), MV88E6190) ? 0xfff0 : 0xff0)
+#define	ATU_PORT_MASK(_sc)		((MVSWITCH((_sc), MV88E6190) || MVSWITCH((_sc), MV88E6190X)) ? 0xfff0 : 0xff0)
 #define	ATU_PORT_SHIFT                  4
 #define	ATU_LAG_MASK                    0xf0
 #define	ATU_LAG_SHIFT                   4