Author: karels
Date: Thu Jun 18 23:57:10 2020
New Revision: 362353
URL: https://svnweb.freebsd.org/changeset/base/362353

Log:
  Add support for bcm54213PE in brgphy.
  
  This chip is used in the Rasperry Pi 4, and is supported by the if_genet
  driver. Currently we use the ukphy mii driver, this patch switches over
  to the brgphy mii driver instead. To support the rgmii-rxid phy mode,
  which is now the default in the Linux dtb, we add support for clock
  skewing.
  
  These changes are taken from OpenBSD and NetBSD, except for the bailout
  in brgphy_bcm54xx_clock_delay() in rgmii mode, which was found necessary
  after testing.
  
  Submitted by: Robert Crowston, crowston at protomail.com
  Differential Revision:        https://reviews.freebsd.org/D25251

Modified:
  head/sys/arm64/broadcom/genet/if_genet.c
  head/sys/dev/mii/brgphy.c
  head/sys/dev/mii/brgphyreg.h
  head/sys/dev/mii/miidevs
  head/sys/dev/mii/miivar.h

Modified: head/sys/arm64/broadcom/genet/if_genet.c
==============================================================================
--- head/sys/arm64/broadcom/genet/if_genet.c    Thu Jun 18 23:31:56 2020        
(r362352)
+++ head/sys/arm64/broadcom/genet/if_genet.c    Thu Jun 18 23:57:10 2020        
(r362353)
@@ -237,7 +237,7 @@ gen_attach(device_t dev)
 {
        struct ether_addr eaddr;
        struct gen_softc *sc;
-       int major, minor, error;
+       int major, minor, error, mii_flags;
        bool eaddr_found;
 
        sc = device_get_softc(dev);
@@ -315,9 +315,24 @@ gen_attach(device_t dev)
        if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp));
 
        /* Attach MII driver */
+       mii_flags = 0;
+       switch (sc->phy_mode)
+       {
+       case MII_CONTYPE_RGMII_ID:
+               mii_flags |= MIIF_RX_DELAY | MIIF_TX_DELAY;
+               break;
+       case MII_CONTYPE_RGMII_RXID:
+               mii_flags |= MIIF_RX_DELAY;
+               break;
+       case MII_CONTYPE_RGMII_TXID:
+               mii_flags |= MIIF_TX_DELAY;
+               break;
+       default:
+               break;
+       }
        error = mii_attach(dev, &sc->miibus, sc->ifp, gen_media_change,
            gen_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY,
-           MIIF_DOPAUSE);
+           mii_flags);
        if (error != 0) {
                device_printf(dev, "cannot attach PHY\n");
                goto fail;
@@ -371,6 +386,7 @@ gen_get_phy_mode(device_t dev)
 
        switch (type) {
        case MII_CONTYPE_RGMII:
+       case MII_CONTYPE_RGMII_ID:
        case MII_CONTYPE_RGMII_RXID:
        case MII_CONTYPE_RGMII_TXID:
                sc->phy_mode = type;
@@ -791,10 +807,17 @@ gen_init_locked(struct gen_softc *sc)
        if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
                return;
 
-       if (sc->phy_mode == MII_CONTYPE_RGMII ||
-           sc->phy_mode == MII_CONTYPE_RGMII_RXID)
-               WR4(sc, GENET_SYS_PORT_CTRL,
-                   GENET_SYS_PORT_MODE_EXT_GPHY);
+       switch (sc->phy_mode)
+       {
+       case MII_CONTYPE_RGMII:
+       case MII_CONTYPE_RGMII_ID:
+       case MII_CONTYPE_RGMII_RXID:
+       case MII_CONTYPE_RGMII_TXID:
+               WR4(sc, GENET_SYS_PORT_CTRL, GENET_SYS_PORT_MODE_EXT_GPHY);
+               break;
+       default:
+               WR4(sc, GENET_SYS_PORT_CTRL, 0);
+       }
 
        gen_set_enaddr(sc);
 
@@ -1649,6 +1672,8 @@ gen_update_link_locked(struct gen_softc *sc)
        val |= GENET_EXT_RGMII_OOB_RGMII_MODE_EN;
        if (sc->phy_mode == MII_CONTYPE_RGMII)
                val |= GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
+       else
+               val &= ~GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
        WR4(sc, GENET_EXT_RGMII_OOB_CTRL, val);
 
        val = RD4(sc, GENET_UMAC_CMD);

Modified: head/sys/dev/mii/brgphy.c
==============================================================================
--- head/sys/dev/mii/brgphy.c   Thu Jun 18 23:31:56 2020        (r362352)
+++ head/sys/dev/mii/brgphy.c   Thu Jun 18 23:57:10 2020        (r362353)
@@ -115,6 +115,7 @@ static void brgphy_fixup_ber_bug(struct mii_softc *);
 static void    brgphy_fixup_crc_bug(struct mii_softc *);
 static void    brgphy_fixup_jitter_bug(struct mii_softc *);
 static void    brgphy_ethernet_wirespeed(struct mii_softc *);
+static void    brgphy_bcm54xx_clock_delay(struct mii_softc *);
 static void    brgphy_jumbo_settings(struct mii_softc *, u_long);
 
 static const struct mii_phydesc brgphys[] = {
@@ -158,6 +159,7 @@ static const struct mii_phydesc brgphys[] = {
        MII_PHY_DESC(BROADCOM3, BCM5720C),
        MII_PHY_DESC(BROADCOM3, BCM57765),
        MII_PHY_DESC(BROADCOM3, BCM57780),
+       MII_PHY_DESC(BROADCOM4, BCM54213PE),
        MII_PHY_DESC(BROADCOM4, BCM5725C),
        MII_PHY_DESC(xxBROADCOM_ALT1, BCM5906),
        MII_PHY_END
@@ -414,6 +416,12 @@ brgphy_service(struct mii_softc *sc, struct mii_data *
                                break;
                        }
                        break;
+               case MII_OUI_BROADCOM4:
+                       switch (sc->mii_mpd_model) {
+                       case MII_MODEL_BROADCOM4_BCM54213PE:
+                               brgphy_bcm54xx_clock_delay(sc);
+                               break;
+                       }
                }
        }
        mii_phy_update(sc, cmd);
@@ -861,6 +869,37 @@ brgphy_ethernet_wirespeed(struct mii_softc *sc)
        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
        val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
        PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4));
+}
+
+static void
+brgphy_bcm54xx_clock_delay(struct mii_softc *sc)
+{
+       uint16_t val;
+
+       if (!(sc->mii_flags & (MIIF_RX_DELAY | MIIF_TX_DELAY)))
+               /* Adjusting the clocks in rgmii mode causes packet losses. */
+               return;
+
+       PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_SHADOW_MISC |
+           BRGPHY_AUXCTL_SHADOW_MISC << BRGPHY_AUXCTL_MISC_READ_SHIFT);
+       val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
+       val &= BRGPHY_AUXCTL_MISC_DATA_MASK;
+       if (sc->mii_flags & MIIF_RX_DELAY)
+               val |= BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
+       else
+               val &= ~BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
+       PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_MISC_WRITE_EN |
+           BRGPHY_AUXCTL_SHADOW_MISC | val);
+
+       PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_CLK_CTRL);
+       val = PHY_READ(sc, BRGPHY_MII_SHADOW_1C);
+       val &= BRGPHY_SHADOW_1C_DATA_MASK;
+       if (sc->mii_flags & MIIF_TX_DELAY)
+               val |= BRGPHY_SHADOW_1C_GTXCLK_EN;
+       else
+               val &= ~BRGPHY_SHADOW_1C_GTXCLK_EN;
+       PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_WRITE_EN |
+           BRGPHY_SHADOW_1C_CLK_CTRL | val);
 }
 
 static void

Modified: head/sys/dev/mii/brgphyreg.h
==============================================================================
--- head/sys/dev/mii/brgphyreg.h        Thu Jun 18 23:31:56 2020        
(r362352)
+++ head/sys/dev/mii/brgphyreg.h        Thu Jun 18 23:57:10 2020        
(r362353)
@@ -293,6 +293,17 @@
 /* Begin: PHY register values for the 5706 PHY         */
 /*******************************************************/
 
+/*
+ * Aux control shadow register, bits 0-2 select function (0x00 to
+ * 0x07).
+ */
+#define        BRGPHY_AUXCTL_SHADOW_MISC       0x07
+#define        BRGPHY_AUXCTL_MISC_DATA_MASK    0x7ff8
+#define        BRGPHY_AUXCTL_MISC_READ_SHIFT   12
+#define        BRGPHY_AUXCTL_MISC_WRITE_EN     0x8000
+#define        BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN 0x0200
+#define        BRGPHY_AUXCTL_MISC_WIRESPEED_EN 0x0010
+
 /* 
  * Shadow register 0x1C, bit 15 is write enable,
  * bits 14-10 select function (0x00 to 0x1F).
@@ -300,6 +311,11 @@
 #define        BRGPHY_MII_SHADOW_1C            0x1C
 #define        BRGPHY_SHADOW_1C_WRITE_EN       0x8000
 #define        BRGPHY_SHADOW_1C_SELECT_MASK    0x7C00
+#define        BRGPHY_SHADOW_1C_DATA_MASK      0x03FF
+
+/* Shadow 0x1C Clock Alignment Control Register (select value 0x03) */
+#define        BRGPHY_SHADOW_1C_CLK_CTRL       (0x03 << 10)
+#define        BRGPHY_SHADOW_1C_GTXCLK_EN      0x0200
 
 /* Shadow 0x1C Mode Control Register (select value 0x1F) */
 #define        BRGPHY_SHADOW_1C_MODE_CTRL      (0x1F << 10)

Modified: head/sys/dev/mii/miidevs
==============================================================================
--- head/sys/dev/mii/miidevs    Thu Jun 18 23:31:56 2020        (r362352)
+++ head/sys/dev/mii/miidevs    Thu Jun 18 23:57:10 2020        (r362353)
@@ -196,6 +196,7 @@ model BROADCOM3 BCM5717C    0x0020 BCM5717C 1000BASE-T me
 model BROADCOM3 BCM5719C       0x0022 BCM5719C 1000BASE-T media interface
 model BROADCOM3 BCM57765       0x0024 BCM57765 1000BASE-T media interface
 model BROADCOM3 BCM5720C       0x0036 BCM5720C 1000BASE-T media interface
+model BROADCOM4 BCM54213PE     0x000a BCM54213PE 1000BASE-T media interface
 model BROADCOM4 BCM5725C       0x0038 BCM5725C 1000BASE-T media interface
 model xxBROADCOM_ALT1 BCM5906  0x0004 BCM5906 10/100baseTX media interface
 

Modified: head/sys/dev/mii/miivar.h
==============================================================================
--- head/sys/dev/mii/miivar.h   Thu Jun 18 23:31:56 2020        (r362352)
+++ head/sys/dev/mii/miivar.h   Thu Jun 18 23:57:10 2020        (r362353)
@@ -134,6 +134,8 @@ typedef struct mii_softc mii_softc_t;
 #define        MIIF_DOPAUSE    0x00000100      /* advertise PAUSE capability */
 #define        MIIF_IS_HPNA    0x00000200      /* is a HomePNA device */
 #define        MIIF_FORCEANEG  0x00000400      /* force auto-negotiation */
+#define        MIIF_RX_DELAY   0x00000800      /* add RX delay */
+#define        MIIF_TX_DELAY   0x00001000      /* add TX delay */
 #define        MIIF_NOMANPAUSE 0x00100000      /* no manual PAUSE selection */
 #define        MIIF_FORCEPAUSE 0x00200000      /* force PAUSE advertisement */
 #define        MIIF_MACPRIV0   0x01000000      /* private to the MAC driver */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to