net: mdiobus: add APIs for modifying a MDIO device register
authorRussell King <rmk+kernel@armlinux.org.uk>
Tue, 17 Mar 2020 14:52:31 +0000 (14:52 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Mar 2020 05:51:16 +0000 (22:51 -0700)
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>
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy-core.c
include/linux/mdio.h
include/linux/phy.h

index 129e606303190d791276b2d836b74fed2f3b3fbf..522760c8bca6ec3d1b90b99c1b8315bb3e0ac23a 100644 (file)
@@ -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
index e083e7a76ada2066e2ea2170256165a107523fee..94cd85b1e49bbb10885f1024a047d0c230b109da 100644 (file)
@@ -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
index a7604248777b7b0c499e4ece7435e8557990eb8d..917e4bb2ed71381de2ee687cad068296265c451a 100644 (file)
@@ -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);
index cb5a2182ba6d6621461459a1867eb83e60ac87b8..36d9dea04016723fc6112f26e1e33d2490c22e97 100644 (file)
@@ -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.