2024-01-03 11:57:28 +00:00
|
|
|
From d63710fc0f1a501fd75a7025e3070a96ffa1645f Mon Sep 17 00:00:00 2001
|
|
|
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
|
|
|
Date: Fri, 15 Dec 2023 14:15:34 +0100
|
|
|
|
Subject: [PATCH 4/4] net: phy: add support for PHY package MMD read/write
|
|
|
|
|
|
|
|
Some PHY in PHY package may require to read/write MMD regs to correctly
|
|
|
|
configure the PHY package.
|
|
|
|
|
|
|
|
Add support for these additional required function in both lock and no
|
|
|
|
lock variant.
|
|
|
|
|
|
|
|
It's assumed that the entire PHY package is either C22 or C45. We use
|
|
|
|
C22 or C45 way of writing/reading to mmd regs based on the passed phydev
|
|
|
|
whether it's C22 or C45.
|
|
|
|
|
|
|
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
|
---
|
|
|
|
drivers/net/phy/phy-core.c | 140 +++++++++++++++++++++++++++++++++++++
|
|
|
|
include/linux/phy.h | 16 +++++
|
|
|
|
2 files changed, 156 insertions(+)
|
|
|
|
|
|
|
|
--- a/drivers/net/phy/phy-core.c
|
|
|
|
+++ b/drivers/net/phy/phy-core.c
|
2024-03-08 14:03:01 +00:00
|
|
|
@@ -651,6 +651,146 @@ int phy_write_mmd(struct phy_device *phy
|
2024-01-03 11:57:28 +00:00
|
|
|
EXPORT_SYMBOL(phy_write_mmd);
|
|
|
|
|
|
|
|
/**
|
|
|
|
+ * __phy_package_read_mmd - read MMD reg relative to PHY package base addr
|
|
|
|
+ * @phydev: The phy_device struct
|
|
|
|
+ * @addr_offset: The offset to be added to PHY package base_addr
|
|
|
|
+ * @devad: The MMD to read from
|
|
|
|
+ * @regnum: The register on the MMD to read
|
|
|
|
+ *
|
|
|
|
+ * Convenience helper for reading a register of an MMD on a given PHY
|
|
|
|
+ * using the PHY package base address. The base address is added to
|
|
|
|
+ * the addr_offset value.
|
|
|
|
+ *
|
|
|
|
+ * Same calling rules as for __phy_read();
|
|
|
|
+ *
|
|
|
|
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
|
|
|
|
+ */
|
|
|
|
+int __phy_package_read_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum)
|
|
|
|
+{
|
|
|
|
+ int addr = phy_package_address(phydev, addr_offset);
|
|
|
|
+
|
|
|
|
+ if (addr < 0)
|
|
|
|
+ return addr;
|
|
|
|
+
|
|
|
|
+ if (regnum > (u16)~0 || devad > 32)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
|
|
|
|
+ regnum);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(__phy_package_read_mmd);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * phy_package_read_mmd - read MMD reg relative to PHY package base addr
|
|
|
|
+ * @phydev: The phy_device struct
|
|
|
|
+ * @addr_offset: The offset to be added to PHY package base_addr
|
|
|
|
+ * @devad: The MMD to read from
|
|
|
|
+ * @regnum: The register on the MMD to read
|
|
|
|
+ *
|
|
|
|
+ * Convenience helper for reading a register of an MMD on a given PHY
|
|
|
|
+ * using the PHY package base address. The base address is added to
|
|
|
|
+ * the addr_offset value.
|
|
|
|
+ *
|
|
|
|
+ * Same calling rules as for phy_read();
|
|
|
|
+ *
|
|
|
|
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
|
|
|
|
+ */
|
|
|
|
+int phy_package_read_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum)
|
|
|
|
+{
|
|
|
|
+ int addr = phy_package_address(phydev, addr_offset);
|
|
|
|
+ int val;
|
|
|
|
+
|
|
|
|
+ if (addr < 0)
|
|
|
|
+ return addr;
|
|
|
|
+
|
|
|
|
+ if (regnum > (u16)~0 || devad > 32)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ phy_lock_mdio_bus(phydev);
|
|
|
|
+ val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
|
|
|
|
+ regnum);
|
|
|
|
+ phy_unlock_mdio_bus(phydev);
|
|
|
|
+
|
|
|
|
+ return val;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(phy_package_read_mmd);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * __phy_package_write_mmd - write MMD reg relative to PHY package base addr
|
|
|
|
+ * @phydev: The phy_device struct
|
|
|
|
+ * @addr_offset: The offset to be added to PHY package base_addr
|
|
|
|
+ * @devad: The MMD to write to
|
|
|
|
+ * @regnum: The register on the MMD to write
|
|
|
|
+ * @val: value to write to @regnum
|
|
|
|
+ *
|
|
|
|
+ * Convenience helper for writing a register of an MMD on a given PHY
|
|
|
|
+ * using the PHY package base address. The base address is added to
|
|
|
|
+ * the addr_offset value.
|
|
|
|
+ *
|
|
|
|
+ * Same calling rules as for __phy_write();
|
|
|
|
+ *
|
|
|
|
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
|
|
|
|
+ */
|
|
|
|
+int __phy_package_write_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum, u16 val)
|
|
|
|
+{
|
|
|
|
+ int addr = phy_package_address(phydev, addr_offset);
|
|
|
|
+
|
|
|
|
+ if (addr < 0)
|
|
|
|
+ return addr;
|
|
|
|
+
|
|
|
|
+ if (regnum > (u16)~0 || devad > 32)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
|
|
|
|
+ regnum, val);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(__phy_package_write_mmd);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * phy_package_write_mmd - write MMD reg relative to PHY package base addr
|
|
|
|
+ * @phydev: The phy_device struct
|
|
|
|
+ * @addr_offset: The offset to be added to PHY package base_addr
|
|
|
|
+ * @devad: The MMD to write to
|
|
|
|
+ * @regnum: The register on the MMD to write
|
|
|
|
+ * @val: value to write to @regnum
|
|
|
|
+ *
|
|
|
|
+ * Convenience helper for writing a register of an MMD on a given PHY
|
|
|
|
+ * using the PHY package base address. The base address is added to
|
|
|
|
+ * the addr_offset value.
|
|
|
|
+ *
|
|
|
|
+ * Same calling rules as for phy_write();
|
|
|
|
+ *
|
|
|
|
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
|
|
|
|
+ */
|
|
|
|
+int phy_package_write_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum, u16 val)
|
|
|
|
+{
|
|
|
|
+ int addr = phy_package_address(phydev, addr_offset);
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (addr < 0)
|
|
|
|
+ return addr;
|
|
|
|
+
|
|
|
|
+ if (regnum > (u16)~0 || devad > 32)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ phy_lock_mdio_bus(phydev);
|
|
|
|
+ ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
|
|
|
|
+ regnum, val);
|
|
|
|
+ phy_unlock_mdio_bus(phydev);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(phy_package_write_mmd);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
* phy_modify_changed - Function for modifying a PHY register
|
|
|
|
* @phydev: the phy_device struct
|
|
|
|
* @regnum: register number to modify
|
|
|
|
--- a/include/linux/phy.h
|
|
|
|
+++ b/include/linux/phy.h
|
2024-03-08 14:03:01 +00:00
|
|
|
@@ -2057,6 +2057,22 @@ static inline int __phy_package_write(st
|
2024-01-03 11:57:28 +00:00
|
|
|
return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
+int __phy_package_read_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum);
|
|
|
|
+
|
|
|
|
+int phy_package_read_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum);
|
|
|
|
+
|
|
|
|
+int __phy_package_write_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum, u16 val);
|
|
|
|
+
|
|
|
|
+int phy_package_write_mmd(struct phy_device *phydev,
|
|
|
|
+ unsigned int addr_offset, int devad,
|
|
|
|
+ u32 regnum, u16 val);
|
|
|
|
+
|
|
|
|
static inline bool __phy_package_set_once(struct phy_device *phydev,
|
|
|
|
unsigned int b)
|
|
|
|
{
|