714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. From d63710fc0f1a501fd75a7025e3070a96ffa1645f Mon Sep 17 00:00:00 2001
  2. From: Christian Marangi <[email protected]>
  3. Date: Fri, 15 Dec 2023 14:15:34 +0100
  4. Subject: [PATCH 4/4] net: phy: add support for PHY package MMD read/write
  5. Some PHY in PHY package may require to read/write MMD regs to correctly
  6. configure the PHY package.
  7. Add support for these additional required function in both lock and no
  8. lock variant.
  9. It's assumed that the entire PHY package is either C22 or C45. We use
  10. C22 or C45 way of writing/reading to mmd regs based on the passed phydev
  11. whether it's C22 or C45.
  12. Signed-off-by: Christian Marangi <[email protected]>
  13. Signed-off-by: David S. Miller <[email protected]>
  14. ---
  15. drivers/net/phy/phy-core.c | 140 +++++++++++++++++++++++++++++++++++++
  16. include/linux/phy.h | 16 +++++
  17. 2 files changed, 156 insertions(+)
  18. --- a/drivers/net/phy/phy-core.c
  19. +++ b/drivers/net/phy/phy-core.c
  20. @@ -639,6 +639,146 @@ int phy_write_mmd(struct phy_device *phy
  21. EXPORT_SYMBOL(phy_write_mmd);
  22. /**
  23. + * __phy_package_read_mmd - read MMD reg relative to PHY package base addr
  24. + * @phydev: The phy_device struct
  25. + * @addr_offset: The offset to be added to PHY package base_addr
  26. + * @devad: The MMD to read from
  27. + * @regnum: The register on the MMD to read
  28. + *
  29. + * Convenience helper for reading a register of an MMD on a given PHY
  30. + * using the PHY package base address. The base address is added to
  31. + * the addr_offset value.
  32. + *
  33. + * Same calling rules as for __phy_read();
  34. + *
  35. + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
  36. + */
  37. +int __phy_package_read_mmd(struct phy_device *phydev,
  38. + unsigned int addr_offset, int devad,
  39. + u32 regnum)
  40. +{
  41. + int addr = phy_package_address(phydev, addr_offset);
  42. +
  43. + if (addr < 0)
  44. + return addr;
  45. +
  46. + if (regnum > (u16)~0 || devad > 32)
  47. + return -EINVAL;
  48. +
  49. + return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
  50. + regnum);
  51. +}
  52. +EXPORT_SYMBOL(__phy_package_read_mmd);
  53. +
  54. +/**
  55. + * phy_package_read_mmd - read MMD reg relative to PHY package base addr
  56. + * @phydev: The phy_device struct
  57. + * @addr_offset: The offset to be added to PHY package base_addr
  58. + * @devad: The MMD to read from
  59. + * @regnum: The register on the MMD to read
  60. + *
  61. + * Convenience helper for reading a register of an MMD on a given PHY
  62. + * using the PHY package base address. The base address is added to
  63. + * the addr_offset value.
  64. + *
  65. + * Same calling rules as for phy_read();
  66. + *
  67. + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
  68. + */
  69. +int phy_package_read_mmd(struct phy_device *phydev,
  70. + unsigned int addr_offset, int devad,
  71. + u32 regnum)
  72. +{
  73. + int addr = phy_package_address(phydev, addr_offset);
  74. + int val;
  75. +
  76. + if (addr < 0)
  77. + return addr;
  78. +
  79. + if (regnum > (u16)~0 || devad > 32)
  80. + return -EINVAL;
  81. +
  82. + phy_lock_mdio_bus(phydev);
  83. + val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
  84. + regnum);
  85. + phy_unlock_mdio_bus(phydev);
  86. +
  87. + return val;
  88. +}
  89. +EXPORT_SYMBOL(phy_package_read_mmd);
  90. +
  91. +/**
  92. + * __phy_package_write_mmd - write MMD reg relative to PHY package base addr
  93. + * @phydev: The phy_device struct
  94. + * @addr_offset: The offset to be added to PHY package base_addr
  95. + * @devad: The MMD to write to
  96. + * @regnum: The register on the MMD to write
  97. + * @val: value to write to @regnum
  98. + *
  99. + * Convenience helper for writing a register of an MMD on a given PHY
  100. + * using the PHY package base address. The base address is added to
  101. + * the addr_offset value.
  102. + *
  103. + * Same calling rules as for __phy_write();
  104. + *
  105. + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
  106. + */
  107. +int __phy_package_write_mmd(struct phy_device *phydev,
  108. + unsigned int addr_offset, int devad,
  109. + u32 regnum, u16 val)
  110. +{
  111. + int addr = phy_package_address(phydev, addr_offset);
  112. +
  113. + if (addr < 0)
  114. + return addr;
  115. +
  116. + if (regnum > (u16)~0 || devad > 32)
  117. + return -EINVAL;
  118. +
  119. + return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
  120. + regnum, val);
  121. +}
  122. +EXPORT_SYMBOL(__phy_package_write_mmd);
  123. +
  124. +/**
  125. + * phy_package_write_mmd - write MMD reg relative to PHY package base addr
  126. + * @phydev: The phy_device struct
  127. + * @addr_offset: The offset to be added to PHY package base_addr
  128. + * @devad: The MMD to write to
  129. + * @regnum: The register on the MMD to write
  130. + * @val: value to write to @regnum
  131. + *
  132. + * Convenience helper for writing a register of an MMD on a given PHY
  133. + * using the PHY package base address. The base address is added to
  134. + * the addr_offset value.
  135. + *
  136. + * Same calling rules as for phy_write();
  137. + *
  138. + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
  139. + */
  140. +int phy_package_write_mmd(struct phy_device *phydev,
  141. + unsigned int addr_offset, int devad,
  142. + u32 regnum, u16 val)
  143. +{
  144. + int addr = phy_package_address(phydev, addr_offset);
  145. + int ret;
  146. +
  147. + if (addr < 0)
  148. + return addr;
  149. +
  150. + if (regnum > (u16)~0 || devad > 32)
  151. + return -EINVAL;
  152. +
  153. + phy_lock_mdio_bus(phydev);
  154. + ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
  155. + regnum, val);
  156. + phy_unlock_mdio_bus(phydev);
  157. +
  158. + return ret;
  159. +}
  160. +EXPORT_SYMBOL(phy_package_write_mmd);
  161. +
  162. +/**
  163. * phy_modify_changed - Function for modifying a PHY register
  164. * @phydev: the phy_device struct
  165. * @regnum: register number to modify
  166. --- a/include/linux/phy.h
  167. +++ b/include/linux/phy.h
  168. @@ -1840,6 +1840,22 @@ static inline int __phy_package_write(st
  169. return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
  170. }
  171. +int __phy_package_read_mmd(struct phy_device *phydev,
  172. + unsigned int addr_offset, int devad,
  173. + u32 regnum);
  174. +
  175. +int phy_package_read_mmd(struct phy_device *phydev,
  176. + unsigned int addr_offset, int devad,
  177. + u32 regnum);
  178. +
  179. +int __phy_package_write_mmd(struct phy_device *phydev,
  180. + unsigned int addr_offset, int devad,
  181. + u32 regnum, u16 val);
  182. +
  183. +int phy_package_write_mmd(struct phy_device *phydev,
  184. + unsigned int addr_offset, int devad,
  185. + u32 regnum, u16 val);
  186. +
  187. static inline bool __phy_package_set_once(struct phy_device *phydev,
  188. unsigned int b)
  189. {