summaryrefslogtreecommitdiff
path: root/drivers/net/phy/broadcom.c
diff options
context:
space:
mode:
authorJon Mason <jon.mason@broadcom.com>2016-11-04 01:10:58 -0400
committerDavid S. Miller <davem@davemloft.net>2016-11-07 13:11:22 -0500
commitb14995ac2527b43a75c9190fbd4efd43fb1f4562 (patch)
treeb414a72189ea4cd2dab7ad8e8139170981016995 /drivers/net/phy/broadcom.c
parent3b9feb60e10e00830f86431b6717fab654664b6b (diff)
net: phy: broadcom: Add BCM54810 PHY entry
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>
Diffstat (limited to 'drivers/net/phy/broadcom.c')
-rw-r--r--drivers/net/phy/broadcom.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 3a64b3d8eca8..b1e32e9be1b3 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -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;
}
@@ -578,6 +621,18 @@ static struct phy_driver broadcom_drivers[] = {
.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,
.name = "Broadcom BCM5482",
@@ -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 },