summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2020-05-26 13:03:11 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2020-06-03 18:08:11 +0100
commit1e2479973d2932d19310a71db98fd897c996378e (patch)
treedb9bf9e77776c0c38ee14c326069e8ba7de1c947 /drivers
parentdb726b2f96e99f6619270932c60ca050fc265e6e (diff)
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: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/phy_device.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index dcc859485b88..26cf5cd2d137 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -661,6 +661,28 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
}
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.
* @bus: the target 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,
{
const int num_ids = ARRAY_SIZE(c45_ids->device_ids);
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
* 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);
if (phy_reg < 0)
return -EIO;