net: phy: broadcom: add support for BCM54811 PHY
authorKevin Lo <kevlo@kevlo.org>
Fri, 15 May 2020 17:24:47 +0000 (01:24 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 May 2020 17:56:31 +0000 (10:56 -0700)
The BCM54811 PHY shares many similarities with the already supported BCM54810
PHY but additionally requires some semi-unique configuration.

Signed-off-by: Kevin Lo <kevlo@kevlo.org>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/broadcom.c
include/linux/brcmphy.h

index 97201d5..8cd8d18 100644 (file)
@@ -195,7 +195,8 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
        if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
            BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
            BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M &&
-           BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54810)
+           BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54810 &&
+           BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811)
                return;
 
        val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
@@ -214,8 +215,10 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
                clk125en = false;
        } else {
                if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
-                       /* Here, bit 0 _enables_ CLK125 when set */
-                       val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
+                       if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811) {
+                               /* Here, bit 0 _enables_ CLK125 when set */
+                               val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
+                       }
                        clk125en = false;
                }
        }
@@ -225,8 +228,13 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
        else
                val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
 
-       if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
-               val |= BCM54XX_SHD_SCR3_TRDDAPD;
+       if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) {
+               if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810 ||
+                   BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54811)
+                       val |= BCM54810_SHD_SCR3_TRDDAPD;
+               else
+                       val |= BCM54XX_SHD_SCR3_TRDDAPD;
+       }
 
        if (orig != val)
                bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
@@ -327,6 +335,32 @@ static int bcm54xx_resume(struct phy_device *phydev)
        return bcm54xx_config_init(phydev);
 }
 
+static int bcm54811_config_init(struct phy_device *phydev)
+{
+       int err, reg;
+
+       /* Disable BroadR-Reach function. */
+       reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
+       reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
+       err = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
+                               reg);
+       if (err < 0)
+               return err;
+
+       err = bcm54xx_config_init(phydev);
+
+       /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
+       if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {
+               reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);
+               err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,
+                                       BCM54612E_LED4_CLK125OUT_EN | reg);
+               if (err < 0)
+                       return err;
+        }
+
+       return err;
+}
+
 static int bcm5482_config_init(struct phy_device *phydev)
 {
        int err, reg;
@@ -723,6 +757,17 @@ static struct phy_driver broadcom_drivers[] = {
        .suspend        = genphy_suspend,
        .resume         = bcm54xx_resume,
 }, {
+       .phy_id         = PHY_ID_BCM54811,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM54811",
+       /* PHY_GBIT_FEATURES */
+       .config_init    = bcm54811_config_init,
+       .config_aneg    = bcm5481_config_aneg,
+       .ack_interrupt  = bcm_phy_ack_intr,
+       .config_intr    = bcm_phy_config_intr,
+       .suspend        = genphy_suspend,
+       .resume         = bcm54xx_resume,
+}, {
        .phy_id         = PHY_ID_BCM5482,
        .phy_id_mask    = 0xfffffff0,
        .name           = "Broadcom BCM5482",
@@ -816,6 +861,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
        { PHY_ID_BCM5464, 0xfffffff0 },
        { PHY_ID_BCM5481, 0xfffffff0 },
        { PHY_ID_BCM54810, 0xfffffff0 },
+       { PHY_ID_BCM54811, 0xfffffff0 },
        { PHY_ID_BCM5482, 0xfffffff0 },
        { PHY_ID_BCM50610, 0xfffffff0 },
        { PHY_ID_BCM50610M, 0xfffffff0 },
index d41624d..6ad4c00 100644 (file)
@@ -17,6 +17,7 @@
 #define PHY_ID_BCM5395                 0x0143bcf0
 #define PHY_ID_BCM53125                        0x03625f20
 #define PHY_ID_BCM54810                        0x03625d00
+#define PHY_ID_BCM54811                        0x03625cc0
 #define PHY_ID_BCM5482                 0x0143bcb0
 #define PHY_ID_BCM5411                 0x00206070
 #define PHY_ID_BCM5421                 0x002060e0
 #define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN        (1 << 0)
 #define BCM54810_SHD_CLK_CTL                   0x3
 #define BCM54810_SHD_CLK_CTL_GTXCLK_EN         (1 << 9)
+#define BCM54810_SHD_SCR3_TRDDAPD              0x0100
 
 /* BCM54612E Registers */
 #define BCM54612E_EXP_SPARE0           (MII_BCM54XX_EXP_SEL_ETC + 0x34)