net: mdiobus: add APIs for modifying a MDIO device register
Add APIs for modifying a MDIO device register, similar to the existing phy_modify() group of functions, but at mdiobus level instead. Adapt __phy_modify_changed() to use the new mdiobus level helper. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
89e3e3ddcb
commit
6cc7cf8125
|
@ -824,6 +824,38 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
|
|||
}
|
||||
EXPORT_SYMBOL(__mdiobus_write);
|
||||
|
||||
/**
|
||||
* __mdiobus_modify_changed - Unlocked version of the mdiobus_modify function
|
||||
* @bus: the mii_bus struct
|
||||
* @addr: the phy address
|
||||
* @regnum: register number to modify
|
||||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*
|
||||
* Read, modify, and if any change, write the register value back to the
|
||||
* device. Any error returns a negative number.
|
||||
*
|
||||
* NOTE: MUST NOT be called from interrupt context.
|
||||
*/
|
||||
int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
|
||||
u16 mask, u16 set)
|
||||
{
|
||||
int new, ret;
|
||||
|
||||
ret = __mdiobus_read(bus, addr, regnum);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new = (ret & ~mask) | set;
|
||||
if (new == ret)
|
||||
return 0;
|
||||
|
||||
ret = __mdiobus_write(bus, addr, regnum, new);
|
||||
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);
|
||||
|
||||
/**
|
||||
* mdiobus_read_nested - Nested version of the mdiobus_read function
|
||||
* @bus: the mii_bus struct
|
||||
|
@ -932,6 +964,30 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
|
|||
}
|
||||
EXPORT_SYMBOL(mdiobus_write);
|
||||
|
||||
/**
|
||||
* mdiobus_modify - Convenience function for modifying a given mdio device
|
||||
* register
|
||||
* @bus: the mii_bus struct
|
||||
* @addr: the phy address
|
||||
* @regnum: register number to write
|
||||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*/
|
||||
int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (WARN_ON_ONCE(in_interrupt()))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&bus->mdio_lock);
|
||||
err = __mdiobus_modify_changed(bus, addr, regnum, mask, set);
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
return err < 0 ? err : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mdiobus_modify);
|
||||
|
||||
/**
|
||||
* mdio_bus_match - determine if given MDIO driver supports the given
|
||||
* MDIO device
|
||||
|
|
|
@ -488,37 +488,6 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
|
|||
}
|
||||
EXPORT_SYMBOL(phy_write_mmd);
|
||||
|
||||
/**
|
||||
* __phy_modify_changed() - Convenience function for modifying a PHY register
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @regnum: register number
|
||||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*
|
||||
* Unlocked helper function which allows a PHY register to be modified as
|
||||
* new register value = (old register value & ~mask) | set
|
||||
*
|
||||
* Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
*/
|
||||
int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
|
||||
u16 set)
|
||||
{
|
||||
int new, ret;
|
||||
|
||||
ret = __phy_read(phydev, regnum);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new = (ret & ~mask) | set;
|
||||
if (new == ret)
|
||||
return 0;
|
||||
|
||||
ret = __phy_write(phydev, regnum, new);
|
||||
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__phy_modify_changed);
|
||||
|
||||
/**
|
||||
* phy_modify_changed - Function for modifying a PHY register
|
||||
* @phydev: the phy_device struct
|
||||
|
|
|
@ -316,11 +316,15 @@ static inline void mii_10gbt_stat_mod_linkmode_lpa_t(unsigned long *advertising,
|
|||
|
||||
int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
|
||||
int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
|
||||
int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
|
||||
u16 mask, u16 set);
|
||||
|
||||
int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
|
||||
int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum);
|
||||
int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
|
||||
int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val);
|
||||
int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask,
|
||||
u16 set);
|
||||
|
||||
int mdiobus_register_device(struct mdio_device *mdiodev);
|
||||
int mdiobus_unregister_device(struct mdio_device *mdiodev);
|
||||
|
|
|
@ -754,6 +754,25 @@ static inline int __phy_write(struct phy_device *phydev, u32 regnum, u16 val)
|
|||
val);
|
||||
}
|
||||
|
||||
/**
|
||||
* __phy_modify_changed() - Convenience function for modifying a PHY register
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @regnum: register number
|
||||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*
|
||||
* Unlocked helper function which allows a PHY register to be modified as
|
||||
* new register value = (old register value & ~mask) | set
|
||||
*
|
||||
* Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
*/
|
||||
static inline int __phy_modify_changed(struct phy_device *phydev, u32 regnum,
|
||||
u16 mask, u16 set)
|
||||
{
|
||||
return __mdiobus_modify_changed(phydev->mdio.bus, phydev->mdio.addr,
|
||||
regnum, mask, set);
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_read_mmd - Convenience function for reading a register
|
||||
* from an MMD on a given PHY.
|
||||
|
|
Loading…
Reference in New Issue