git: da8a529bc01f - main - mgb: support for PCI11414.

From: Ruslan Bukin <br_at_FreeBSD.org>
Date: Tue, 13 Oct 2026 17:42:43 UTC
The branch main has been updated by br:

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

commit da8a529bc01f5fdfdd5308ff6fd9a2bc52359069
Author:     Ruslan Bukin <br@FreeBSD.org>
AuthorDate: 2026-10-13 17:39:24 +0000
Commit:     Ruslan Bukin <br@FreeBSD.org>
CommitDate: 2026-10-13 17:41:14 +0000

    mgb: support for PCI11414.
    
    Add support for Microchip PCI11414 Gigabit Ethernet Controller.
    
    The PCI11414 is used on the CHERI VITA 57.1 PCIe Extension Board.
    
    - Add PCI11414 device ID
    - Add support for SGMII mode. Read the programmed strap configuration
      and enable SGMII operation when configured. Bypass the MII interface
      in SGMII mode.
    - Increase the DMA descriptor ring size.
    
    Reviewed by:    emaste
    Sponsored by:   EPSRC ("UKRI3001: CHERI Research Centre")
    Differential Revision:  https://reviews.freebsd.org/D60539
---
 sys/dev/mgb/if_mgb.c | 110 ++++++++++++++++++++++++++++++++++++++-------------
 sys/dev/mgb/if_mgb.h |  33 +++++++++++++++-
 2 files changed, 115 insertions(+), 28 deletions(-)

diff --git a/sys/dev/mgb/if_mgb.c b/sys/dev/mgb/if_mgb.c
index 887d95dc457c..7fb98a85fc1a 100644
--- a/sys/dev/mgb/if_mgb.c
+++ b/sys/dev/mgb/if_mgb.c
@@ -91,6 +91,8 @@ static const pci_vendor_info_t mgb_vendor_info_array[] = {
 	    "Microchip LAN7430 PCIe Gigabit Ethernet Controller"),
 	PVID(MGB_MICROCHIP_VENDOR_ID, MGB_LAN7431_DEVICE_ID,
 	    "Microchip LAN7431 PCIe Gigabit Ethernet Controller"),
+	PVID(MGB_MICROCHIP_VENDOR_ID, MGB_PCI11414_DEVICE_ID,
+	    "Microchip PCI11414 PCIe Gigabit Ethernet Controller"),
 	PVID_END
 };
 
@@ -328,14 +330,48 @@ mgb_register(device_t dev)
 	return (&mgb_sctx_init);
 }
 
+static int
+mgb_mii_attach(struct mgb_softc *sc)
+{
+	struct mii_data *miid;
+	if_softc_ctx_t scctx;
+	int phyaddr;
+	int error;
+
+	scctx = iflib_get_softc_ctx(sc->ctx);
+
+	switch (pci_get_device(sc->dev)) {
+	case MGB_LAN7430_DEVICE_ID:
+		phyaddr = 1;
+		break;
+	case MGB_LAN7431_DEVICE_ID:
+	default:
+		phyaddr = MII_PHY_ANY;
+		break;
+	}
+
+	/* XXX: Would be nice(r) if locked methods were here */
+	error = mii_attach(sc->dev, &sc->miibus, iflib_get_ifp(sc->ctx),
+	    mgb_media_change, mgb_media_status,
+	    BMSR_DEFCAPMASK, phyaddr, MII_OFFSET_ANY, MIIF_DOPAUSE);
+	if (error != 0) {
+		device_printf(sc->dev, "Failed to attach MII interface\n");
+		return (error);
+	}
+
+	miid = device_get_softc(sc->miibus);
+	scctx->isc_media = &miid->mii_media;
+
+	return (0);
+}
+
 static int
 mgb_attach_pre(if_ctx_t ctx)
 {
 	struct mgb_softc *sc;
 	if_softc_ctx_t scctx;
-	int error, phyaddr, rid;
+	int error, rid;
 	struct ether_addr hwaddr;
-	struct mii_data *miid;
 
 	sc = iflib_get_softc(ctx);
 	sc->ctx = ctx;
@@ -395,28 +431,12 @@ mgb_attach_pre(if_ctx_t ctx)
 		goto fail;
 	}
 
-	switch (pci_get_device(sc->dev)) {
-	case MGB_LAN7430_DEVICE_ID:
-		phyaddr = 1;
-		break;
-	case MGB_LAN7431_DEVICE_ID:
-	default:
-		phyaddr = MII_PHY_ANY;
-		break;
-	}
-
-	/* XXX: Would be nice(r) if locked methods were here */
-	error = mii_attach(sc->dev, &sc->miibus, iflib_get_ifp(ctx),
-	    mgb_media_change, mgb_media_status,
-	    BMSR_DEFCAPMASK, phyaddr, MII_OFFSET_ANY, MIIF_DOPAUSE);
-	if (error != 0) {
-		device_printf(sc->dev, "Failed to attach MII interface\n");
-		goto fail;
+	if (!sc->sgmii_en) {
+		error = mgb_mii_attach(sc);
+		if (error)
+			goto fail;
 	}
 
-	miid = device_get_softc(sc->miibus);
-	scctx->isc_media = &miid->mii_media;
-
 	scctx->isc_msix_bar = pci_msix_table_bar(sc->dev);
 	/** Setup PBA BAR **/
 	rid = pci_msix_pba_bar(sc->dev);
@@ -447,6 +467,11 @@ mgb_attach_pre(if_ctx_t ctx)
 	CSR_WRITE_REG(sc, MGB_INTR_VEC_TX_MAP, 0);
 	CSR_WRITE_REG(sc, MGB_INTR_VEC_OTHER_MAP, 0);
 
+	if (sc->sgmii_en) {
+		/* Unsure which speed to set, use 1Gbps as default. */
+		iflib_link_state_change(ctx, LINK_STATE_UP, IF_Mbps(1000));
+	}
+
 	return (0);
 
 fail:
@@ -598,8 +623,6 @@ mgb_init(if_ctx_t ctx)
 	int error;
 
 	sc = iflib_get_softc(ctx);
-	miid = device_get_softc(sc->miibus);
-	device_printf(sc->dev, "running init ...\n");
 
 	error = mgb_dma_init(sc);
 	if (error != 0) {
@@ -615,6 +638,10 @@ mgb_init(if_ctx_t ctx)
 	    MGB_RFE_ALLOW_MULTICAST |
 	    MGB_RFE_ALLOW_UNICAST);
 
+	if (sc->sgmii_en)
+		return;
+
+	miid = device_get_softc(sc->miibus);
 	error = mii_mediachg(miid);
 	/* Not much we can do if this fails. */
 	if (error)
@@ -1190,10 +1217,11 @@ mgb_test_bar(struct mgb_softc *sc)
 	id_rev = CSR_READ_REG(sc, 0);
 	dev_id = id_rev >> 16;
 	if (dev_id == MGB_LAN7430_DEVICE_ID ||
-	    dev_id == MGB_LAN7431_DEVICE_ID) {
+	    dev_id == MGB_LAN7431_DEVICE_ID ||
+	    dev_id == MGB_PCI11414_DEVICE_ID) {
 		return (0);
 	} else {
-		device_printf(sc->dev, "ID check failed.\n");
+		device_printf(sc->dev, "ID check failed: 0x%x\n", dev_id);
 		return (ENXIO);
 	}
 }
@@ -1457,7 +1485,11 @@ mgb_hw_teardown(struct mgb_softc *sc)
 static int
 mgb_hw_init(struct mgb_softc *sc)
 {
-	int error = 0;
+	uint32_t sgmii_ctl;
+	uint32_t reg;
+	int error;
+
+	error = 0;
 
 	error = mgb_hw_reset(sc);
 	if (error != 0)
@@ -1469,6 +1501,30 @@ mgb_hw_init(struct mgb_softc *sc)
 	if (error != 0)
 		goto fail;
 
+	/* Enable SGMII if needed. */
+	reg = CSR_READ_REG(sc, STRAP_READ);
+	if (bootverbose)
+		device_printf(sc->dev, "  Strap: %#b\n", reg,
+			"\020"
+			"\01ADV_PM_DISABLE"
+			"\02RGMII_RXC_DELAY_EN"
+			"\03RGMII_TXC_DELAY_EN"
+			"\04BASE_X"
+			"\05SGMII_2_5G"
+			"\06SGMII_REFCLK"
+			"\07SGMII_EN"
+			"\10RMII_EN"
+			"\27USE_SGMII_EN"
+			"\30USE_RMII_EN");
+	if ((reg & STRAP_READ_USE_SGMII_EN) != 0 &&
+	    (reg & STRAP_READ_SGMII_EN) != 0) {
+		sgmii_ctl = CSR_READ_REG(sc, SGMII_CTL);
+		sgmii_ctl |= SGMII_CTL_SGMII_ENABLE;
+		sgmii_ctl &= ~SGMII_CTL_SGMII_POWER_DN;
+		CSR_WRITE_REG(sc, SGMII_CTL, sgmii_ctl);
+		sc->sgmii_en = true;
+	}
+
 	error = mgb_dmac_reset(sc);
 	if (error != 0)
 		goto fail;
diff --git a/sys/dev/mgb/if_mgb.h b/sys/dev/mgb/if_mgb.h
index ebae9bb29e55..c5289fd6e80a 100644
--- a/sys/dev/mgb/if_mgb.h
+++ b/sys/dev/mgb/if_mgb.h
@@ -33,6 +33,7 @@
 #define MGB_MICROCHIP_VENDOR_ID		0x1055
 #define MGB_LAN7430_DEVICE_ID		0x7430
 #define MGB_LAN7431_DEVICE_ID		0x7431
+#define MGB_PCI11414_DEVICE_ID		0xA041
 
 #define MGB_TIMEOUT			(500)
 
@@ -85,6 +86,19 @@
 #define MGB_PHY_RESET			0x10
 #define MGB_PHY_READY			0x80
 
+/* Strap configuration */
+#define	STRAP_READ			0x0C
+#define	STRAP_READ_USE_RMII_EN		(1 << 23)
+#define	STRAP_READ_USE_SGMII_EN		(1 << 22)
+#define	STRAP_READ_RMII_EN		(1 << 7)
+#define	STRAP_READ_SGMII_EN		(1 << 6)
+#define	STRAP_READ_SGMII_REFCLK		(1 << 5)
+#define	STRAP_READ_SGMII_2_5G		(1 << 4)
+#define	STRAP_READ_BASE_X		(1 << 3)
+#define	STRAP_READ_RGMII_TXC_DELAY_EN	(1 << 2)
+#define	STRAP_READ_RGMII_RXC_DELAY_EN	(1 << 1)
+#define	STRAP_READ_ADV_PM_DISABLE	(1 << 0)
+
 /** FIFO Controller **/
 #define MGB_FCT_TX_CTL			0xC4
 #define MGB_FCT_RX_CTL			0xAC
@@ -129,7 +143,7 @@
  *
  **/
 /* In linux driver these numbers are 50 and 65 for tx and rx .... */
-#define MGB_DMA_RING_SIZE		16 /* in programming guide, this number is 100 */
+#define MGB_DMA_RING_SIZE		1024 /* in programming guide, this number is 100 */
 #define MGB_DMA_MAXSEGS			32
 #define MGB_DMA_REG(reg, _channel)	((reg) | ((_channel) << 6))
 #define MGB_DMA_RING_LIST_SIZE		\
@@ -194,6 +208,22 @@
 #define MGB_MII_WRITE			0x2
 #define MGB_MII_BUSY			0x1
 
+#define	SGMII_ACC			0x720
+#define	SGMII_ACC_SGMII_BZY		(1 << 31)
+#define	SGMII_ACC_SGMII_WR		(1 << 30)
+#define	SGMII_ACC_SGMII_MMD_SHIFT	16
+#define	SGMII_ACC_SGMII_MMD_MASK	0xf0000
+#define	SGMII_ACC_SGMII_MMD_VSR		(1 << 15)
+#define	SGMII_ACC_SGMII_ADDR_SHIFT	0
+#define	SGMII_ACC_SGMII_ADDR_MASK	0xffff
+#define	SGMII_DATA			0x724
+#define	SGMII_DATA_SHIFT		0
+#define	SGMII_DATA_MASK			0xffff
+#define	SGMII_CTL			0x728
+#define	SGMII_CTL_SGMII_ENABLE		(1 << 31)
+#define	SGMII_CTL_LINK_STATUS_SOURCE	(1 << 8)
+#define	SGMII_CTL_SGMII_POWER_DN	(1 << 1)
+
 /** Interrupt registers **/
 #define MGB_INTR_STS			0x780
 #define MGB_INTR_SET			0x784 /* This triggers a particular interrupt */
@@ -325,6 +355,7 @@ struct mgb_softc {
 	struct mgb_ring_data		 rx_ring_data;
 	struct mgb_ring_data		 tx_ring_data;
 
+	bool				sgmii_en;
 };
 
 #endif /* _IF_MGB_H_ */