git: dc4c75c9a3c3 - main - smsc: Support external PHY

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Fri, 23 Oct 2026 22:01:28 UTC
The branch main has been updated by emaste:

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

commit dc4c75c9a3c3611af451da13990e49e267551475
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2026-10-14 01:04:24 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2026-10-23 22:00:48 +0000

    smsc: Support external PHY
    
    SMSC_HW_CFG_PSEL indicates that an external PHY is present. Skip the
    internal PHY initialization when set and store the ID of the detected
    PHY.
    
    Reviewed by:    br
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D60744
---
 sys/dev/usb/net/if_smsc.c    | 39 +++++++++++++++++++++++++++++++--------
 sys/dev/usb/net/if_smscreg.h |  1 +
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 5803a5bd1bcf..3144eb7e8917 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -1449,11 +1449,12 @@ smsc_chip_init(struct smsc_softc *sc)
 	/* Vlan */
 	smsc_write_reg(sc, SMSC_VLAN1, (uint32_t)ETHERTYPE_VLAN);
 
-	/*
-	 * Initialise the PHY
-	 */
-	if ((err = smsc_phy_init(sc)) != 0)
-		goto init_failed;
+	if ((sc->sc_flags & SMSC_FLAG_EXT_PHY) == 0) {
+		/* Initialise the PHY */
+		err = smsc_phy_init(sc);
+		if (err != 0)
+			goto init_failed;
+	}
 
 	/*
 	 * Start TX
@@ -1621,14 +1622,12 @@ smsc_attach_post(struct usb_ether *ue)
 {
 	struct smsc_softc *sc = uether_getsc(ue);
 	struct ether_addr eaddr;
-	uint32_t mac_h, mac_l;
+	uint32_t hwcfg, mac_h, mac_l;
 	int err;
 	int i;
 
 	smsc_dbg_printf(sc, "smsc_attach_post\n");
 
-	/* Setup some of the basics */
-	sc->sc_phyno = 1;
 
 	/* Attempt to get the mac address, if an EEPROM is not attached this
 	 * will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC
@@ -1636,6 +1635,15 @@ smsc_attach_post(struct usb_ether *ue)
 	 */
 	memset(sc->sc_ue.ue_eaddr, 0xff, ETHER_ADDR_LEN);
 
+	smsc_read_reg(sc, SMSC_HW_CFG, &hwcfg);
+	if (hwcfg & SMSC_HW_CFG_PSEL) {
+		smsc_dbg_printf(sc, "HW_CFG indicates external PHY\n");
+		sc->sc_flags |= SMSC_FLAG_EXT_PHY;
+		sc->sc_phyno = MII_PHY_ANY;
+	} else {
+		sc->sc_phyno = 1;
+	}
+
 	/* Check if there is already a MAC address in the register */
 	if ((smsc_read_reg(sc, SMSC_MAC_ADDRL, &mac_l) == 0) &&
 	    (smsc_read_reg(sc, SMSC_MAC_ADDRH, &mac_h) == 0)) {
@@ -1688,6 +1696,8 @@ static int
 smsc_attach_post_sub(struct usb_ether *ue)
 {
 	struct smsc_softc *sc;
+	struct mii_softc *miisc;
+	struct mii_data *mii;
 	if_t ifp;
 	int error;
 
@@ -1718,6 +1728,19 @@ smsc_attach_post_sub(struct usb_ether *ue)
 	error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
 	    uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
 	    BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, 0);
+
+	if (error != 0)
+		goto fail;
+
+	if (sc->sc_phyno == MII_PHY_ANY) {
+		/* Store the actual PHY address we found. */
+		mii = device_get_softc(ue->ue_miibus);
+		miisc = LIST_FIRST(&mii->mii_phys);
+		if (miisc != NULL)
+			sc->sc_phyno = miisc->mii_phy;
+	}
+
+fail:
 	bus_topo_unlock();
 
 	return (error);
diff --git a/sys/dev/usb/net/if_smscreg.h b/sys/dev/usb/net/if_smscreg.h
index 1d27b661b16e..be18caf7627a 100644
--- a/sys/dev/usb/net/if_smscreg.h
+++ b/sys/dev/usb/net/if_smscreg.h
@@ -268,6 +268,7 @@ struct smsc_softc {
 	uint32_t          sc_flags;
 #define	SMSC_FLAG_LINK      0x0001
 #define	SMSC_FLAG_LAN9514   0x1000	/* LAN9514 */
+#define	SMSC_FLAG_EXT_PHY   0x2000	/* External PHY (HW_CFG.PSEL) */
 };
 
 #define	SMSC_LOCK(_sc)             mtx_lock(&(_sc)->sc_mtx)