Skip to content

Commit

Permalink
net: bcmgenet: Determine PHY type before scanning MDIO bus
Browse files Browse the repository at this point in the history
Our internal GPHY might be powered off before we attempt scanning the
MDIO bus and bind a driver to it. The way we are currently determining
whether a PHY is internal or not is done *after* we have successfully
matched its driver. If the PHY is powered down, it will not respond to
the MDIO bus, so we will not be able to bind a driver to it.

Our Device Tree for GENET interfaces specifies a "phy-mode" value:
"internal" which tells if this internal uses an internal PHY or not.

If of_get_phy_mode() fails to parse the 'phy-mode' property, do an
additional manual lookup, and if we find "internal" set the
corresponding internal variable accordingly.

Replace all uses of phy_is_internal() with a check against
priv->internal_phy to avoid having to rely on whether or not
priv->phydev is set correctly.

Fixes: 1c1008c ("net: bcmgenet: add main driver file")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Florian Fainelli authored and David S. Miller committed Jul 21, 2015
1 parent bd4060a commit c624f89
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 12 deletions.
14 changes: 7 additions & 7 deletions drivers/net/ethernet/broadcom/genet/bcmgenet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,7 @@ static int init_umac(struct bcmgenet_priv *priv)
int0_enable |= UMAC_IRQ_TXDMA_DONE;

/* Monitor cable plug/unplugged event for internal PHY */
if (phy_is_internal(priv->phydev)) {
if (priv->internal_phy) {
int0_enable |= UMAC_IRQ_LINK_EVENT;
} else if (priv->ext_phy) {
int0_enable |= UMAC_IRQ_LINK_EVENT;
Expand Down Expand Up @@ -2631,7 +2631,7 @@ static int bcmgenet_open(struct net_device *dev)
/* If this is an internal GPHY, power it back on now, before UniMAC is
* brought out of reset as absolutely no UniMAC activity is allowed
*/
if (phy_is_internal(priv->phydev))
if (priv->internal_phy)
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);

/* take MAC out of reset */
Expand All @@ -2650,7 +2650,7 @@ static int bcmgenet_open(struct net_device *dev)

bcmgenet_set_hw_addr(priv, dev->dev_addr);

if (phy_is_internal(priv->phydev)) {
if (priv->internal_phy) {
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= EXT_ENERGY_DET_MASK;
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
Expand Down Expand Up @@ -2756,7 +2756,7 @@ static int bcmgenet_close(struct net_device *dev)
free_irq(priv->irq0, priv);
free_irq(priv->irq1, priv);

if (phy_is_internal(priv->phydev))
if (priv->internal_phy)
ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);

if (!IS_ERR(priv->clk))
Expand Down Expand Up @@ -3318,7 +3318,7 @@ static int bcmgenet_suspend(struct device *d)
if (device_may_wakeup(d) && priv->wolopts) {
ret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
clk_prepare_enable(priv->clk_wol);
} else if (phy_is_internal(priv->phydev)) {
} else if (priv->internal_phy) {
ret = bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
}

Expand Down Expand Up @@ -3347,7 +3347,7 @@ static int bcmgenet_resume(struct device *d)
/* If this is an internal GPHY, power it back on now, before UniMAC is
* brought out of reset as absolutely no UniMAC activity is allowed
*/
if (phy_is_internal(priv->phydev))
if (priv->internal_phy)
bcmgenet_power_up(priv, GENET_POWER_PASSIVE);

bcmgenet_umac_reset(priv);
Expand All @@ -3369,7 +3369,7 @@ static int bcmgenet_resume(struct device *d)

bcmgenet_set_hw_addr(priv, dev->dev_addr);

if (phy_is_internal(priv->phydev)) {
if (priv->internal_phy) {
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= EXT_ENERGY_DET_MASK;
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/broadcom/genet/bcmgenet.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ struct bcmgenet_priv {
/* MDIO bus variables */
wait_queue_head_t wq;
struct phy_device *phydev;
bool internal_phy;
struct device_node *phy_dn;
struct device_node *mdio_dn;
struct mii_bus *mii_bus;
Expand Down
29 changes: 24 additions & 5 deletions drivers/net/ethernet/broadcom/genet/bcmmii.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
u32 port_ctrl;
u32 reg;

priv->ext_phy = !phy_is_internal(priv->phydev) &&
priv->ext_phy = !priv->internal_phy &&
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);

if (phy_is_internal(priv->phydev))
if (priv->internal_phy)
priv->phy_interface = PHY_INTERFACE_MODE_NA;

switch (priv->phy_interface) {
Expand All @@ -248,7 +248,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)

bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);

if (phy_is_internal(priv->phydev)) {
if (priv->internal_phy) {
phy_name = "internal PHY";
bcmgenet_internal_phy_setup(dev);
} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
Expand Down Expand Up @@ -386,7 +386,7 @@ static int bcmgenet_mii_probe(struct net_device *dev)
/* The internal PHY has its link interrupts routed to the
* Ethernet MAC ISRs
*/
if (phy_is_internal(priv->phydev))
if (priv->internal_phy)
priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT;
else
priv->mii_bus->irq[phydev->addr] = PHY_POLL;
Expand Down Expand Up @@ -479,7 +479,9 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
{
struct device_node *dn = priv->pdev->dev.of_node;
struct device *kdev = &priv->pdev->dev;
const char *phy_mode_str = NULL;
char *compat;
int phy_mode;
int ret;

compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
Expand All @@ -503,7 +505,24 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);

/* Get the link mode */
priv->phy_interface = of_get_phy_mode(dn);
phy_mode = of_get_phy_mode(dn);
priv->phy_interface = phy_mode;

/* We need to specifically look up whether this PHY interface is internal
* or not *before* we even try to probe the PHY driver over MDIO as we
* may have shut down the internal PHY for power saving purposes.
*/
if (phy_mode < 0) {
ret = of_property_read_string(dn, "phy-mode", &phy_mode_str);
if (ret < 0) {
dev_err(kdev, "invalid PHY mode property\n");
return ret;
}

priv->phy_interface = PHY_INTERFACE_MODE_NA;
if (!strcasecmp(phy_mode_str, "internal"))
priv->internal_phy = true;
}

return 0;
}
Expand Down

0 comments on commit c624f89

Please sign in to comment.