phy_package.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * PHY package support
  4. */
  5. #include <linux/of.h>
  6. #include <linux/phy.h>
  7. #include "phylib.h"
  8. #include "phylib-internal.h"
  9. /**
  10. * struct phy_package_shared - Shared information in PHY packages
  11. * @base_addr: Base PHY address of PHY package used to combine PHYs
  12. * in one package and for offset calculation of phy_package_read/write
  13. * @np: Pointer to the Device Node if PHY package defined in DT
  14. * @refcnt: Number of PHYs connected to this shared data
  15. * @flags: Initialization of PHY package
  16. * @priv_size: Size of the shared private data @priv
  17. * @priv: Driver private data shared across a PHY package
  18. *
  19. * Represents a shared structure between different phydev's in the same
  20. * package, for example a quad PHY. See phy_package_join() and
  21. * phy_package_leave().
  22. */
  23. struct phy_package_shared {
  24. u8 base_addr;
  25. /* With PHY package defined in DT this points to the PHY package node */
  26. struct device_node *np;
  27. refcount_t refcnt;
  28. unsigned long flags;
  29. size_t priv_size;
  30. /* private data pointer */
  31. /* note that this pointer is shared between different phydevs and
  32. * the user has to take care of appropriate locking. It is allocated
  33. * and freed automatically by phy_package_join() and
  34. * phy_package_leave().
  35. */
  36. void *priv;
  37. };
  38. struct device_node *phy_package_get_node(struct phy_device *phydev)
  39. {
  40. return phydev->shared->np;
  41. }
  42. EXPORT_SYMBOL_GPL(phy_package_get_node);
  43. void *phy_package_get_priv(struct phy_device *phydev)
  44. {
  45. return phydev->shared->priv;
  46. }
  47. EXPORT_SYMBOL_GPL(phy_package_get_priv);
  48. static int phy_package_address(struct phy_device *phydev,
  49. unsigned int addr_offset)
  50. {
  51. struct phy_package_shared *shared = phydev->shared;
  52. u8 base_addr = shared->base_addr;
  53. if (addr_offset >= PHY_MAX_ADDR - base_addr)
  54. return -EIO;
  55. /* we know that addr will be in the range 0..31 and thus the
  56. * implicit cast to a signed int is not a problem.
  57. */
  58. return base_addr + addr_offset;
  59. }
  60. int __phy_package_read(struct phy_device *phydev, unsigned int addr_offset,
  61. u32 regnum)
  62. {
  63. int addr = phy_package_address(phydev, addr_offset);
  64. if (addr < 0)
  65. return addr;
  66. return __mdiobus_read(phydev->mdio.bus, addr, regnum);
  67. }
  68. EXPORT_SYMBOL_GPL(__phy_package_read);
  69. int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset,
  70. u32 regnum, u16 val)
  71. {
  72. int addr = phy_package_address(phydev, addr_offset);
  73. if (addr < 0)
  74. return addr;
  75. return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
  76. }
  77. EXPORT_SYMBOL_GPL(__phy_package_write);
  78. /**
  79. * __phy_package_read_mmd - read MMD reg relative to PHY package base addr
  80. * @phydev: The phy_device struct
  81. * @addr_offset: The offset to be added to PHY package base_addr
  82. * @devad: The MMD to read from
  83. * @regnum: The register on the MMD to read
  84. *
  85. * Convenience helper for reading a register of an MMD on a given PHY
  86. * using the PHY package base address. The base address is added to
  87. * the addr_offset value.
  88. *
  89. * Same calling rules as for __phy_read();
  90. *
  91. * NOTE: It's assumed that the entire PHY package is either C22 or C45.
  92. */
  93. int __phy_package_read_mmd(struct phy_device *phydev,
  94. unsigned int addr_offset, int devad,
  95. u32 regnum)
  96. {
  97. int addr = phy_package_address(phydev, addr_offset);
  98. if (addr < 0)
  99. return addr;
  100. if (regnum > (u16)~0 || devad > 32)
  101. return -EINVAL;
  102. return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
  103. regnum);
  104. }
  105. EXPORT_SYMBOL(__phy_package_read_mmd);
  106. /**
  107. * __phy_package_write_mmd - write MMD reg relative to PHY package base addr
  108. * @phydev: The phy_device struct
  109. * @addr_offset: The offset to be added to PHY package base_addr
  110. * @devad: The MMD to write to
  111. * @regnum: The register on the MMD to write
  112. * @val: value to write to @regnum
  113. *
  114. * Convenience helper for writing a register of an MMD on a given PHY
  115. * using the PHY package base address. The base address is added to
  116. * the addr_offset value.
  117. *
  118. * Same calling rules as for __phy_write();
  119. *
  120. * NOTE: It's assumed that the entire PHY package is either C22 or C45.
  121. */
  122. int __phy_package_write_mmd(struct phy_device *phydev,
  123. unsigned int addr_offset, int devad,
  124. u32 regnum, u16 val)
  125. {
  126. int addr = phy_package_address(phydev, addr_offset);
  127. if (addr < 0)
  128. return addr;
  129. if (regnum > (u16)~0 || devad > 32)
  130. return -EINVAL;
  131. return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
  132. regnum, val);
  133. }
  134. EXPORT_SYMBOL(__phy_package_write_mmd);
  135. static bool __phy_package_set_once(struct phy_device *phydev, unsigned int b)
  136. {
  137. struct phy_package_shared *shared = phydev->shared;
  138. if (!shared)
  139. return false;
  140. return !test_and_set_bit(b, &shared->flags);
  141. }
  142. bool phy_package_init_once(struct phy_device *phydev)
  143. {
  144. return __phy_package_set_once(phydev, 0);
  145. }
  146. EXPORT_SYMBOL_GPL(phy_package_init_once);
  147. bool phy_package_probe_once(struct phy_device *phydev)
  148. {
  149. return __phy_package_set_once(phydev, 1);
  150. }
  151. EXPORT_SYMBOL_GPL(phy_package_probe_once);
  152. /**
  153. * phy_package_join - join a common PHY group
  154. * @phydev: target phy_device struct
  155. * @base_addr: cookie and base PHY address of PHY package for offset
  156. * calculation of global register access
  157. * @priv_size: if non-zero allocate this amount of bytes for private data
  158. *
  159. * This joins a PHY group and provides a shared storage for all phydevs in
  160. * this group. This is intended to be used for packages which contain
  161. * more than one PHY, for example a quad PHY transceiver.
  162. *
  163. * The base_addr parameter serves as cookie which has to have the same values
  164. * for all members of one group and as the base PHY address of the PHY package
  165. * for offset calculation to access generic registers of a PHY package.
  166. * Usually, one of the PHY addresses of the different PHYs in the package
  167. * provides access to these global registers.
  168. * The address which is given here, will be used in the phy_package_read()
  169. * and phy_package_write() convenience functions as base and added to the
  170. * passed offset in those functions.
  171. *
  172. * This will set the shared pointer of the phydev to the shared storage.
  173. * If this is the first call for a this cookie the shared storage will be
  174. * allocated. If priv_size is non-zero, the given amount of bytes are
  175. * allocated for the priv member.
  176. *
  177. * Returns < 1 on error, 0 on success. Esp. calling phy_package_join()
  178. * with the same cookie but a different priv_size is an error.
  179. */
  180. int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size)
  181. {
  182. struct mii_bus *bus = phydev->mdio.bus;
  183. struct phy_package_shared *shared;
  184. int ret;
  185. if (base_addr < 0 || base_addr >= PHY_MAX_ADDR)
  186. return -EINVAL;
  187. mutex_lock(&bus->shared_lock);
  188. shared = bus->shared[base_addr];
  189. if (!shared) {
  190. ret = -ENOMEM;
  191. shared = kzalloc_obj(*shared);
  192. if (!shared)
  193. goto err_unlock;
  194. if (priv_size) {
  195. shared->priv = kzalloc(priv_size, GFP_KERNEL);
  196. if (!shared->priv)
  197. goto err_free;
  198. shared->priv_size = priv_size;
  199. }
  200. shared->base_addr = base_addr;
  201. shared->np = NULL;
  202. refcount_set(&shared->refcnt, 1);
  203. bus->shared[base_addr] = shared;
  204. } else {
  205. ret = -EINVAL;
  206. if (priv_size && priv_size != shared->priv_size)
  207. goto err_unlock;
  208. refcount_inc(&shared->refcnt);
  209. }
  210. mutex_unlock(&bus->shared_lock);
  211. phydev->shared = shared;
  212. return 0;
  213. err_free:
  214. kfree(shared);
  215. err_unlock:
  216. mutex_unlock(&bus->shared_lock);
  217. return ret;
  218. }
  219. EXPORT_SYMBOL_GPL(phy_package_join);
  220. /**
  221. * of_phy_package_join - join a common PHY group in PHY package
  222. * @phydev: target phy_device struct
  223. * @priv_size: if non-zero allocate this amount of bytes for private data
  224. *
  225. * This is a variant of phy_package_join for PHY package defined in DT.
  226. *
  227. * The parent node of the @phydev is checked as a valid PHY package node
  228. * structure (by matching the node name "ethernet-phy-package") and the
  229. * base_addr for the PHY package is passed to phy_package_join.
  230. *
  231. * With this configuration the shared struct will also have the np value
  232. * filled to use additional DT defined properties in PHY specific
  233. * probe_once and config_init_once PHY package OPs.
  234. *
  235. * Returns < 0 on error, 0 on success. Esp. calling phy_package_join()
  236. * with the same cookie but a different priv_size is an error. Or a parent
  237. * node is not detected or is not valid or doesn't match the expected node
  238. * name for PHY package.
  239. */
  240. int of_phy_package_join(struct phy_device *phydev, size_t priv_size)
  241. {
  242. struct device_node *node = phydev->mdio.dev.of_node;
  243. struct device_node *package_node;
  244. u32 base_addr;
  245. int ret;
  246. if (!node)
  247. return -EINVAL;
  248. package_node = of_get_parent(node);
  249. if (!package_node)
  250. return -EINVAL;
  251. if (!of_node_name_eq(package_node, "ethernet-phy-package")) {
  252. ret = -EINVAL;
  253. goto exit;
  254. }
  255. if (of_property_read_u32(package_node, "reg", &base_addr)) {
  256. ret = -EINVAL;
  257. goto exit;
  258. }
  259. ret = phy_package_join(phydev, base_addr, priv_size);
  260. if (ret)
  261. goto exit;
  262. phydev->shared->np = package_node;
  263. return 0;
  264. exit:
  265. of_node_put(package_node);
  266. return ret;
  267. }
  268. EXPORT_SYMBOL_GPL(of_phy_package_join);
  269. /**
  270. * phy_package_leave - leave a common PHY group
  271. * @phydev: target phy_device struct
  272. *
  273. * This leaves a PHY group created by phy_package_join(). If this phydev
  274. * was the last user of the shared data between the group, this data is
  275. * freed. Resets the phydev->shared pointer to NULL.
  276. */
  277. void phy_package_leave(struct phy_device *phydev)
  278. {
  279. struct phy_package_shared *shared = phydev->shared;
  280. struct mii_bus *bus = phydev->mdio.bus;
  281. if (!shared)
  282. return;
  283. /* Decrease the node refcount on leave if present */
  284. if (shared->np)
  285. of_node_put(shared->np);
  286. if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
  287. bus->shared[shared->base_addr] = NULL;
  288. mutex_unlock(&bus->shared_lock);
  289. kfree(shared->priv);
  290. kfree(shared);
  291. }
  292. phydev->shared = NULL;
  293. }
  294. EXPORT_SYMBOL_GPL(phy_package_leave);
  295. static void devm_phy_package_leave(struct device *dev, void *res)
  296. {
  297. phy_package_leave(*(struct phy_device **)res);
  298. }
  299. /**
  300. * devm_phy_package_join - resource managed phy_package_join()
  301. * @dev: device that is registering this PHY package
  302. * @phydev: target phy_device struct
  303. * @base_addr: cookie and base PHY address of PHY package for offset
  304. * calculation of global register access
  305. * @priv_size: if non-zero allocate this amount of bytes for private data
  306. *
  307. * Managed phy_package_join(). Shared storage fetched by this function,
  308. * phy_package_leave() is automatically called on driver detach. See
  309. * phy_package_join() for more information.
  310. */
  311. int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
  312. int base_addr, size_t priv_size)
  313. {
  314. struct phy_device **ptr;
  315. int ret;
  316. ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
  317. GFP_KERNEL);
  318. if (!ptr)
  319. return -ENOMEM;
  320. ret = phy_package_join(phydev, base_addr, priv_size);
  321. if (!ret) {
  322. *ptr = phydev;
  323. devres_add(dev, ptr);
  324. } else {
  325. devres_free(ptr);
  326. }
  327. return ret;
  328. }
  329. EXPORT_SYMBOL_GPL(devm_phy_package_join);
  330. /**
  331. * devm_of_phy_package_join - resource managed of_phy_package_join()
  332. * @dev: device that is registering this PHY package
  333. * @phydev: target phy_device struct
  334. * @priv_size: if non-zero allocate this amount of bytes for private data
  335. *
  336. * Managed of_phy_package_join(). Shared storage fetched by this function,
  337. * phy_package_leave() is automatically called on driver detach. See
  338. * of_phy_package_join() for more information.
  339. */
  340. int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev,
  341. size_t priv_size)
  342. {
  343. struct phy_device **ptr;
  344. int ret;
  345. ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
  346. GFP_KERNEL);
  347. if (!ptr)
  348. return -ENOMEM;
  349. ret = of_phy_package_join(phydev, priv_size);
  350. if (!ret) {
  351. *ptr = phydev;
  352. devres_add(dev, ptr);
  353. } else {
  354. devres_free(ptr);
  355. }
  356. return ret;
  357. }
  358. EXPORT_SYMBOL_GPL(devm_of_phy_package_join);
  359. MODULE_DESCRIPTION("PHY package support");
  360. MODULE_LICENSE("GPL");