diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r-- | drivers/net/phy/phy.c | 177 |
1 files changed, 160 insertions, 17 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 60b5839b40..abd78b2c80 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -20,8 +20,6 @@ #include <linux/phy.h> #include <linux/err.h> -#define PHY_AN_TIMEOUT 10 - static struct phy_driver genphy_driver; /** @@ -330,7 +328,7 @@ struct phy_device *of_phy_register_fixed_link(struct device_node *np, static struct phy_device *of_mdio_find_phy(struct eth_device *edev) { - struct device_d *dev; + struct device *dev; struct device_node *phy_node; struct mii_bus *bus; int addr; @@ -338,16 +336,18 @@ static struct phy_device *of_mdio_find_phy(struct eth_device *edev) if (!IS_ENABLED(CONFIG_OFDEVICE)) return NULL; - if (!edev->parent || !edev->parent->device_node) + if (!edev->parent || !edev->parent->of_node) return NULL; - phy_node = of_parse_phandle(edev->parent->device_node, "phy-handle", 0); + phy_node = of_parse_phandle(edev->parent->of_node, "phy-handle", 0); if (!phy_node) - phy_node = of_parse_phandle(edev->parent->device_node, "phy", 0); + phy_node = of_parse_phandle(edev->parent->of_node, "phy", 0); if (!phy_node) - phy_node = of_parse_phandle(edev->parent->device_node, "phy-device", 0); + phy_node = of_parse_phandle(edev->parent->of_node, + "phy-device", 0); if (!phy_node) { - phy_node = of_get_child_by_name(edev->parent->device_node, "fixed-link"); + phy_node = of_get_child_by_name(edev->parent->of_node, + "fixed-link"); if (phy_node) return of_phy_register_fixed_link(phy_node, edev); } @@ -358,7 +358,7 @@ static struct phy_device *of_mdio_find_phy(struct eth_device *edev) if (!of_property_read_u32(phy_node, "reg", &addr)) { of_device_ensure_probed(phy_node->parent); for_each_mii_bus(bus) { - if (bus->parent->device_node == phy_node->parent) { + if (bus->dev.of_node == phy_node->parent) { struct phy_device *phy = mdiobus_scan(bus, addr); if (!IS_ERR(phy)) return phy; @@ -367,7 +367,7 @@ static struct phy_device *of_mdio_find_phy(struct eth_device *edev) } bus_for_each_device(&mdio_bus_type, dev) { - if (dev->device_node == phy_node) + if (dev->of_node == phy_node) return container_of(dev, struct phy_device, dev); } @@ -462,7 +462,7 @@ int phy_device_connect(struct eth_device *edev, struct mii_bus *bus, int addr, ret = -ENODEV; out: if (ret) - puts("Unable to find a PHY (unknown ID?)\n"); + dev_err(&edev->dev, "Unable to find a PHY (unknown ID?)\n"); return ret; } @@ -675,7 +675,7 @@ int genphy_aneg_done(struct phy_device *phydev) /* Restart auto-negotiation if remote fault */ if (bmsr & BMSR_RFAULT) { - puts("PHY remote fault detected\n" + dev_info(&phydev->dev, "PHY remote fault detected\n" "PHY restarting auto-negotiation\n"); phy_write(phydev, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); @@ -819,14 +819,14 @@ int genphy_read_status(struct phy_device *phydev) return 0; } -static inline void mmd_phy_indirect(struct phy_device *phydev, int prtad, - int devad) +static inline void mmd_phy_indirect(struct phy_device *phydev, int devad, + u16 regnum) { /* Write the desired MMD Devad */ phy_write(phydev, MII_MMD_CTRL, devad); /* Write the desired MMD register address */ - phy_write(phydev, MII_MMD_DATA, prtad); + phy_write(phydev, MII_MMD_DATA, regnum); /* Select the Function : DATA with no post increment */ phy_write(phydev, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); @@ -850,7 +850,10 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad) { u32 ret; - mmd_phy_indirect(phydev, prtad, devad); + phydev_warn(phydev, "%s is deprectated use phy_read_mmd instead\n", + __func__); + + mmd_phy_indirect(phydev, devad, prtad); /* Read the content of the MMD's selected register */ ret = phy_read(phydev, MII_MMD_DATA); @@ -876,12 +879,150 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad) void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, int devad, u16 data) { - mmd_phy_indirect(phydev, prtad, devad); + phydev_warn(phydev, "%s is deprectated use phy_write_mmd instead\n", + __func__); + + mmd_phy_indirect(phydev, devad, prtad); /* Write the data into MMD's selected register */ phy_write(phydev, MII_MMD_DATA, data); } +/** + * phy_modify_mmd_indirect - Convenience function for modifying a MMD register + * @phydev: phy device + * @prtad: MMD Address + * @devad: MMD DEVAD + * @mask: bit mask of bits to clear + * @set: new value of bits set in @mask + * + */ +int phy_modify_mmd_indirect(struct phy_device *phydev, int prtad, int devad, + u16 mask, u16 set) +{ + int ret; + + phydev_warn(phydev, "%s is deprectated use phy_modify_mmd instead\n", + __func__); + + ret = phy_read_mmd_indirect(phydev, prtad, devad); + if (ret < 0) + return ret; + + phy_write_mmd_indirect(phydev, prtad, devad, (ret & ~mask) | set); + + return 0; +} + +/** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * + * Same rules as for phy_read(); + */ +int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) +{ + struct mii_bus *bus = phydev->bus; + int phy_addr = phydev->addr; + + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + + if (phydev->is_c45) { + phydev_warn(phydev, "Clause45 is not supported yet\n"); + return -EOPNOTSUPP; + } + + mmd_phy_indirect(phydev, devad, regnum); + + /* Read the content of the MMD's selected register */ + return mdiobus_read(bus, phy_addr, MII_MMD_DATA); +} +EXPORT_SYMBOL(phy_read_mmd); + +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * + * Same rules as for phy_write(); + */ +int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) +{ + struct mii_bus *bus = phydev->bus; + int phy_addr = phydev->addr; + + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + + if (phydev->is_c45) { + phydev_warn(phydev, "Clause45 is not supported yet\n"); + return -EOPNOTSUPP; + } + + mmd_phy_indirect(phydev, devad, regnum); + + /* Write the data into MMD's selected register */ + mdiobus_write(bus, phy_addr, MII_MMD_DATA, val); + + return 0; +} +EXPORT_SYMBOL(phy_write_mmd); + +/** + * phy_modify_mmd_changed - Function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * Returns negative errno, 0 if there was no change, and 1 in case of change + */ +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int new, ret; + + ret = phy_read_mmd(phydev, devad, regnum); + if (ret < 0) + return ret; + + new = (ret & ~mask) | set; + if (new == ret) + return 0; + + ret = phy_write_mmd(phydev, devad, regnum, new); + + return ret < 0 ? ret : 1; +} +EXPORT_SYMBOL_GPL(phy_modify_mmd_changed); + +/** + * phy_modify_mmd - Convenience function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + */ +int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set); + + return ret < 0 ? ret : 0; +} +EXPORT_SYMBOL_GPL(phy_modify_mmd); + int genphy_config_init(struct phy_device *phydev) { int val; @@ -933,6 +1074,8 @@ int phy_driver_register(struct phy_driver *phydrv) { phydrv->drv.bus = &mdio_bus_type; + phydrv->is_phy = true; + if (!phydrv->config_init) phydrv->config_init = genphy_config_init; |