summaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
authorMarco Felsch <m.felsch@pengutronix.de>2023-08-11 12:26:52 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2023-08-14 08:19:33 +0200
commitc88783c2f6ade8458370f9009391db1e9b0901f1 (patch)
tree56faae04965136e0d839178e40661c26dd8d0a18 /drivers/net/phy/phy.c
parentd1ef2e991523b7c68618cd5b48f92306840214bf (diff)
downloadbarebox-c88783c2f6ade8458370f9009391db1e9b0901f1.tar.gz
barebox-c88783c2f6ade8458370f9009391db1e9b0901f1.tar.xz
net: phy: import phy_{read,write,modify}_mmd helpers from Linux
Linux have added helper functions to access and modify the mmd registers. The helpers are clause22/45 agnostic and can handle both the same way. Since barebox does not have clause45 support we need to inform the user that this is not supported at the moment. Therefore we also need the is_c45 flag which is ported from Linux as well. Signed-off-by: Marco Felsch <m.felsch@pengutronix.de> Link: https://lore.barebox.org/20230811102657.271931-6-m.felsch@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c1b8cb46e6..4cabb436e4 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -905,6 +905,115 @@ int phy_modify_mmd_indirect(struct phy_device *phydev, int prtad, int devad,
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;