Commit c746053d authored by Russell King's avatar Russell King Committed by David S. Miller

net: phy: add support for probing MMDs >= 8 for devices-in-package

Add support for probing MMDs above 7 for a valid devices-in-package
specifier, but only probe the vendor MMDs for this if they also report
that there the device is present in status register 2.  This avoids
issues where the MMD is implemented, but does not provide IEEE 802.3
compliant registers (such as the MV88X3310 PHY.)
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 439625a7
...@@ -661,6 +661,28 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id, ...@@ -661,6 +661,28 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
} }
EXPORT_SYMBOL(phy_device_create); EXPORT_SYMBOL(phy_device_create);
/* phy_c45_probe_present - checks to see if a MMD is present in the package
* @bus: the target MII bus
* @prtad: PHY package address on the MII bus
* @devad: PHY device (MMD) address
*
* Read the MDIO_STAT2 register, and check whether a device is responding
* at this address.
*
* Returns: negative error number on bus access error, zero if no device
* is responding, or positive if a device is present.
*/
static int phy_c45_probe_present(struct mii_bus *bus, int prtad, int devad)
{
int stat2;
stat2 = mdiobus_c45_read(bus, prtad, devad, MDIO_STAT2);
if (stat2 < 0)
return stat2;
return (stat2 & MDIO_STAT2_DEVPRST) == MDIO_STAT2_DEVPRST_VAL;
}
/* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers. /* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers.
* @bus: the target MII bus * @bus: the target MII bus
* @addr: PHY address on the MII bus * @addr: PHY address on the MII bus
...@@ -711,12 +733,26 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, ...@@ -711,12 +733,26 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr,
{ {
const int num_ids = ARRAY_SIZE(c45_ids->device_ids); const int num_ids = ARRAY_SIZE(c45_ids->device_ids);
u32 *devs = &c45_ids->devices_in_package; u32 *devs = &c45_ids->devices_in_package;
int i, phy_reg; int i, ret, phy_reg;
/* Find first non-zero Devices In package. Device zero is reserved /* Find first non-zero Devices In package. Device zero is reserved
* for 802.3 c45 complied PHYs, so don't probe it at first. * for 802.3 c45 complied PHYs, so don't probe it at first.
*/ */
for (i = 1; i < num_ids && *devs == 0; i++) { for (i = 1; i < MDIO_MMD_NUM && *devs == 0; i++) {
if (i == MDIO_MMD_VEND1 || i == MDIO_MMD_VEND2) {
/* Check that there is a device present at this
* address before reading the devices-in-package
* register to avoid reading garbage from the PHY.
* Some PHYs (88x3310) vendor space is not IEEE802.3
* compliant.
*/
ret = phy_c45_probe_present(bus, addr, i);
if (ret < 0)
return -EIO;
if (!ret)
continue;
}
phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, devs); phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, devs);
if (phy_reg < 0) if (phy_reg < 0)
return -EIO; return -EIO;
......
...@@ -388,6 +388,8 @@ enum phy_state { ...@@ -388,6 +388,8 @@ enum phy_state {
PHY_CABLETEST, PHY_CABLETEST,
}; };
#define MDIO_MMD_NUM 32
/** /**
* struct phy_c45_device_ids - 802.3-c45 Device Identifiers * struct phy_c45_device_ids - 802.3-c45 Device Identifiers
* @devices_in_package: Bit vector of devices present. * @devices_in_package: Bit vector of devices present.
......
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