net: phy: broadcom: Add BCM54810 PHY entry
authorJon Mason <jon.mason@broadcom.com>
Fri, 4 Nov 2016 05:10:58 +0000 (01:10 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Nov 2016 18:11:22 +0000 (13:11 -0500)
The BCM54810 PHY requires some semi-unique configuration, which results
in some additional configuration in addition to the standard config.
Also, some users of the BCM54810 require the PHY lanes to be swapped.
Since there is no way to detect this, add a device tree query to see if
it is applicable.

Inspired-by: Vikas Soni <vsoni@broadcom.com>
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/Kconfig
drivers/net/phy/broadcom.c
include/linux/brcmphy.h

index ff31c10a3485d4e82680b9d25e6e0f4765f68c01..d3fcfd29191339c60fc624620bc0a28f6f7df10d 100644 (file)
@@ -217,7 +217,7 @@ config BROADCOM_PHY
        select BCM_NET_PHYLIB
        ---help---
          Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
-         BCM5481 and BCM5482 PHYs.
+         BCM5481, BCM54810 and BCM5482 PHYs.
 
 config CICADA_PHY
        tristate "Cicada PHYs"
index 3a64b3d8eca8132a8f5c4807cfadf307e87ddd83..b1e32e9be1b3bc35689523a1f7a25d2881100560 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/brcmphy.h>
-
+#include <linux/of.h>
 
 #define BRCM_PHY_MODEL(phydev) \
        ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
@@ -45,6 +45,34 @@ static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
        return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
 }
 
+static int bcm54810_config(struct phy_device *phydev)
+{
+       int rc, val;
+
+       val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
+       val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
+       rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
+                              val);
+       if (rc < 0)
+               return rc;
+
+       val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+       val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
+       val |= MII_BCM54XX_AUXCTL_MISC_WREN;
+       rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+                                 val);
+       if (rc < 0)
+               return rc;
+
+       val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
+       val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
+       rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
 static int bcm50610_a0_workaround(struct phy_device *phydev)
 {
@@ -217,6 +245,12 @@ static int bcm54xx_config_init(struct phy_device *phydev)
            (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
                bcm54xx_adjust_rxrefclk(phydev);
 
+       if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
+               err = bcm54810_config(phydev);
+               if (err)
+                       return err;
+       }
+
        bcm54xx_phydsp_config(phydev);
 
        return 0;
@@ -314,6 +348,7 @@ static int bcm5482_read_status(struct phy_device *phydev)
 
 static int bcm5481_config_aneg(struct phy_device *phydev)
 {
+       struct device_node *np = phydev->mdio.dev.of_node;
        int ret;
 
        /* Aneg firsly. */
@@ -344,6 +379,14 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
                phy_write(phydev, 0x18, reg);
        }
 
+       if (of_property_read_bool(np, "enet-phy-lane-swap")) {
+               /* Lane Swap - Undocumented register...magic! */
+               ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
+                                       0x11B);
+               if (ret < 0)
+                       return ret;
+       }
+
        return ret;
 }
 
@@ -577,6 +620,18 @@ static struct phy_driver broadcom_drivers[] = {
        .read_status    = genphy_read_status,
        .ack_interrupt  = bcm_phy_ack_intr,
        .config_intr    = bcm_phy_config_intr,
+}, {
+       .phy_id         = PHY_ID_BCM54810,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM54810",
+       .features       = PHY_GBIT_FEATURES |
+                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = bcm54xx_config_init,
+       .config_aneg    = bcm5481_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = bcm_phy_ack_intr,
+       .config_intr    = bcm_phy_config_intr,
 }, {
        .phy_id         = PHY_ID_BCM5482,
        .phy_id_mask    = 0xfffffff0,
@@ -661,6 +716,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
        { PHY_ID_BCM54616S, 0xfffffff0 },
        { PHY_ID_BCM5464, 0xfffffff0 },
        { PHY_ID_BCM5481, 0xfffffff0 },
+       { PHY_ID_BCM54810, 0xfffffff0 },
        { PHY_ID_BCM5482, 0xfffffff0 },
        { PHY_ID_BCM50610, 0xfffffff0 },
        { PHY_ID_BCM50610M, 0xfffffff0 },
index 0ed66914b61c435571c0638960032735e72159df..848dc508ef578d33e4add231c38a39c02991c7e3 100644 (file)
@@ -13,6 +13,7 @@
 #define PHY_ID_BCM5241                 0x0143bc30
 #define PHY_ID_BCMAC131                        0x0143bc70
 #define PHY_ID_BCM5481                 0x0143bca0
+#define PHY_ID_BCM54810                        0x03625d00
 #define PHY_ID_BCM5482                 0x0143bcb0
 #define PHY_ID_BCM5411                 0x00206070
 #define PHY_ID_BCM5421                 0x002060e0
@@ -56,6 +57,7 @@
 #define PHY_BRCM_EXT_IBND_TX_ENABLE    0x00002000
 #define PHY_BRCM_CLEAR_RGMII_MODE      0x00004000
 #define PHY_BRCM_DIS_TXCRXC_NOENRGY    0x00008000
+
 /* Broadcom BCM7xxx specific workarounds */
 #define PHY_BRCM_7XXX_REV(x)           (((x) >> 8) & 0xff)
 #define PHY_BRCM_7XXX_PATCH(x)         ((x) & 0xff)
 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC     0x7000
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC        0x0007
 #define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT  12
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN  (1 << 8)
 
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MASK        0x0007
 
 #define BCM5482_SSD_SGMII_SLAVE_EN     0x0002  /* Slave mode enable */
 #define BCM5482_SSD_SGMII_SLAVE_AD     0x0001  /* Slave auto-detection */
 
+/* BCM54810 Registers */
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL   (MII_BCM54XX_EXP_SEL_ER + 0x90)
+#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)
+
 
 /*****************************************************************************/
 /* Fast Ethernet Transceiver definitions. */