123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- From d63710fc0f1a501fd75a7025e3070a96ffa1645f Mon Sep 17 00:00:00 2001
- From: Christian Marangi <[email protected]>
- 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 <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- 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
- @@ -651,6 +651,146 @@ int phy_write_mmd(struct phy_device *phy
- 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
- @@ -2057,6 +2057,22 @@ static inline int __phy_package_write(st
- 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)
- {
|