Commit eb25a4e7 authored by David S. Miller's avatar David S. Miller

Merge branch 'of_mdio'

Florian Fainelli says:

====================
net: of_mdio improvements

This patchset contains a few improvements to the MDIO device tree parsing
code such as refactoring and parsing the "max-speed" property which is
defined in the ePAPR specification.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9d2c881a 9f2b0936
...@@ -22,6 +22,7 @@ Optional Properties: ...@@ -22,6 +22,7 @@ Optional Properties:
specifications. If neither of these are specified, the default is to specifications. If neither of these are specified, the default is to
assume clause 22. The compatible list may also contain other assume clause 22. The compatible list may also contain other
elements. elements.
- max-speed: Maximum PHY supported speed (10, 100, 1000...)
Example: Example:
......
...@@ -122,7 +122,6 @@ struct buffer_state { ...@@ -122,7 +122,6 @@ struct buffer_state {
* @link: PHY's last seen link state. * @link: PHY's last seen link state.
* @duplex: PHY's last set duplex mode. * @duplex: PHY's last set duplex mode.
* @speed: PHY's last set speed. * @speed: PHY's last set speed.
* @max_speed: Maximum supported by current system network data-rate.
*/ */
struct arc_emac_priv { struct arc_emac_priv {
/* Devices */ /* Devices */
...@@ -152,7 +151,6 @@ struct arc_emac_priv { ...@@ -152,7 +151,6 @@ struct arc_emac_priv {
unsigned int link; unsigned int link;
unsigned int duplex; unsigned int duplex;
unsigned int speed; unsigned int speed;
unsigned int max_speed;
}; };
/** /**
......
...@@ -381,17 +381,7 @@ static int arc_emac_open(struct net_device *ndev) ...@@ -381,17 +381,7 @@ static int arc_emac_open(struct net_device *ndev)
phy_dev->autoneg = AUTONEG_ENABLE; phy_dev->autoneg = AUTONEG_ENABLE;
phy_dev->speed = 0; phy_dev->speed = 0;
phy_dev->duplex = 0; phy_dev->duplex = 0;
phy_dev->advertising = phy_dev->supported; phy_dev->advertising &= phy_dev->supported;
if (priv->max_speed > 100) {
phy_dev->advertising &= PHY_GBIT_FEATURES;
} else if (priv->max_speed <= 100) {
phy_dev->advertising &= PHY_BASIC_FEATURES;
if (priv->max_speed <= 10) {
phy_dev->advertising &= ~SUPPORTED_100baseT_Half;
phy_dev->advertising &= ~SUPPORTED_100baseT_Full;
}
}
priv->last_rx_bd = 0; priv->last_rx_bd = 0;
...@@ -704,14 +694,6 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -704,14 +694,6 @@ static int arc_emac_probe(struct platform_device *pdev)
/* Set poll rate so that it polls every 1 ms */ /* Set poll rate so that it polls every 1 ms */
arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000); arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000);
/* Get max speed of operation from device tree */
if (of_property_read_u32(pdev->dev.of_node, "max-speed",
&priv->max_speed)) {
dev_err(&pdev->dev, "failed to retrieve <max-speed> from device tree\n");
err = -EINVAL;
goto out;
}
ndev->irq = irq; ndev->irq = irq;
dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq); dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq);
......
...@@ -22,6 +22,71 @@ ...@@ -22,6 +22,71 @@
MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed)
{
phydev->supported |= PHY_DEFAULT_FEATURES;
switch (max_speed) {
default:
return;
case SPEED_1000:
phydev->supported |= PHY_1000BT_FEATURES;
case SPEED_100:
phydev->supported |= PHY_100BT_FEATURES;
case SPEED_10:
phydev->supported |= PHY_10BT_FEATURES;
}
}
static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child,
u32 addr)
{
struct phy_device *phy;
bool is_c45;
int rc, prev_irq;
u32 max_speed = 0;
is_c45 = of_device_is_compatible(child,
"ethernet-phy-ieee802.3-c45");
phy = get_phy_device(mdio, addr, is_c45);
if (!phy || IS_ERR(phy))
return 1;
if (mdio->irq) {
prev_irq = mdio->irq[addr];
mdio->irq[addr] =
irq_of_parse_and_map(child, 0);
if (!mdio->irq[addr])
mdio->irq[addr] = prev_irq;
}
/* Associate the OF node with the device structure so it
* can be looked up later */
of_node_get(child);
phy->dev.of_node = child;
/* All data is now stored in the phy struct;
* register it */
rc = phy_device_register(phy);
if (rc) {
phy_device_free(phy);
of_node_put(child);
return 1;
}
/* Set phydev->supported based on the "max-speed" property
* if present */
if (!of_property_read_u32(child, "max-speed", &max_speed))
of_set_phy_supported(phy, max_speed);
dev_dbg(&mdio->dev, "registered phy %s at address %i\n",
child->name, addr);
return 0;
}
/** /**
* of_mdiobus_register - Register mii_bus and create PHYs from the device tree * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
* @mdio: pointer to mii_bus structure * @mdio: pointer to mii_bus structure
...@@ -32,11 +97,10 @@ MODULE_LICENSE("GPL"); ...@@ -32,11 +97,10 @@ MODULE_LICENSE("GPL");
*/ */
int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
{ {
struct phy_device *phy;
struct device_node *child; struct device_node *child;
const __be32 *paddr; const __be32 *paddr;
u32 addr; u32 addr;
bool is_c45, scanphys = false; bool scanphys = false;
int rc, i, len; int rc, i, len;
/* Mask out all PHYs from auto probing. Instead the PHYs listed in /* Mask out all PHYs from auto probing. Instead the PHYs listed in
...@@ -67,44 +131,15 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) ...@@ -67,44 +131,15 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
} }
addr = be32_to_cpup(paddr); addr = be32_to_cpup(paddr);
if (addr >= 32) { if (addr >= PHY_MAX_ADDR) {
dev_err(&mdio->dev, "%s PHY address %i is too large\n", dev_err(&mdio->dev, "%s PHY address %i is too large\n",
child->full_name, addr); child->full_name, addr);
continue; continue;
} }
if (mdio->irq) { rc = of_mdiobus_register_phy(mdio, child, addr);
mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (rc)
if (!mdio->irq[addr])
mdio->irq[addr] = PHY_POLL;
}
is_c45 = of_device_is_compatible(child,
"ethernet-phy-ieee802.3-c45");
phy = get_phy_device(mdio, addr, is_c45);
if (!phy || IS_ERR(phy)) {
dev_err(&mdio->dev,
"cannot get PHY at address %i\n",
addr);
continue;
}
/* Associate the OF node with the device structure so it
* can be looked up later */
of_node_get(child);
phy->dev.of_node = child;
/* All data is now stored in the phy struct; register it */
rc = phy_device_register(phy);
if (rc) {
phy_device_free(phy);
of_node_put(child);
continue; continue;
}
dev_dbg(&mdio->dev, "registered phy %s at address %i\n",
child->name, addr);
} }
if (!scanphys) if (!scanphys)
...@@ -117,9 +152,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) ...@@ -117,9 +152,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
if (paddr) if (paddr)
continue; continue;
is_c45 = of_device_is_compatible(child,
"ethernet-phy-ieee802.3-c45");
for (addr = 0; addr < PHY_MAX_ADDR; addr++) { for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
/* skip already registered PHYs */ /* skip already registered PHYs */
if (mdio->phy_map[addr]) if (mdio->phy_map[addr])
...@@ -129,34 +161,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) ...@@ -129,34 +161,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
dev_info(&mdio->dev, "scan phy %s at address %i\n", dev_info(&mdio->dev, "scan phy %s at address %i\n",
child->name, addr); child->name, addr);
phy = get_phy_device(mdio, addr, is_c45); rc = of_mdiobus_register_phy(mdio, child, addr);
if (!phy || IS_ERR(phy)) if (rc)
continue; continue;
if (mdio->irq) {
mdio->irq[addr] =
irq_of_parse_and_map(child, 0);
if (!mdio->irq[addr])
mdio->irq[addr] = PHY_POLL;
}
/* Associate the OF node with the device structure so it
* can be looked up later */
of_node_get(child);
phy->dev.of_node = child;
/* All data is now stored in the phy struct;
* register it */
rc = phy_device_register(phy);
if (rc) {
phy_device_free(phy);
of_node_put(child);
continue;
}
dev_info(&mdio->dev, "registered phy %s at address %i\n",
child->name, addr);
break;
} }
} }
......
...@@ -27,18 +27,27 @@ ...@@ -27,18 +27,27 @@
#include <linux/atomic.h> #include <linux/atomic.h>
#define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ #define PHY_DEFAULT_FEATURES (SUPPORTED_Autoneg | \
SUPPORTED_10baseT_Full | \
SUPPORTED_100baseT_Half | \
SUPPORTED_100baseT_Full | \
SUPPORTED_Autoneg | \
SUPPORTED_TP | \ SUPPORTED_TP | \
SUPPORTED_MII) SUPPORTED_MII)
#define PHY_GBIT_FEATURES (PHY_BASIC_FEATURES | \ #define PHY_10BT_FEATURES (SUPPORTED_10baseT_Half | \
SUPPORTED_1000baseT_Half | \ SUPPORTED_10baseT_Full)
#define PHY_100BT_FEATURES (SUPPORTED_100baseT_Half | \
SUPPORTED_100baseT_Full)
#define PHY_1000BT_FEATURES (SUPPORTED_1000baseT_Half | \
SUPPORTED_1000baseT_Full) SUPPORTED_1000baseT_Full)
#define PHY_BASIC_FEATURES (PHY_10BT_FEATURES | \
PHY_100BT_FEATURES | \
PHY_DEFAULT_FEATURES)
#define PHY_GBIT_FEATURES (PHY_BASIC_FEATURES | \
PHY_1000BT_FEATURES)
/* /*
* Set phydev->irq to PHY_POLL if interrupts are not supported, * Set phydev->irq to PHY_POLL if interrupts are not supported,
* or not desired for this PHY. Set to PHY_IGNORE_INTERRUPT if * or not desired for this PHY. Set to PHY_IGNORE_INTERRUPT if
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment