xilinx_axienet_mdio.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * MDIO bus driver for the Xilinx Axi Ethernet device
  4. *
  5. * Copyright (c) 2009 Secret Lab Technologies, Ltd.
  6. * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
  7. * Copyright (c) 2010 - 2011 PetaLogix
  8. * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
  9. * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
  10. */
  11. #include <linux/clk.h>
  12. #include <linux/of_address.h>
  13. #include <linux/of_mdio.h>
  14. #include <linux/jiffies.h>
  15. #include <linux/iopoll.h>
  16. #include "xilinx_axienet.h"
  17. #define MAX_MDIO_FREQ 2500000 /* 2.5 MHz */
  18. #define DEFAULT_HOST_CLOCK 150000000 /* 150 MHz */
  19. /* Wait till MDIO interface is ready to accept a new transaction.*/
  20. static int axienet_mdio_wait_until_ready(struct axienet_local *lp)
  21. {
  22. u32 val;
  23. return readx_poll_timeout(axinet_ior_read_mcr, lp,
  24. val, val & XAE_MDIO_MCR_READY_MASK,
  25. 1, 20000);
  26. }
  27. /**
  28. * axienet_mdio_read - MDIO interface read function
  29. * @bus: Pointer to mii bus structure
  30. * @phy_id: Address of the PHY device
  31. * @reg: PHY register to read
  32. *
  33. * Return: The register contents on success, -ETIMEDOUT on a timeout
  34. *
  35. * Reads the contents of the requested register from the requested PHY
  36. * address by first writing the details into MCR register. After a while
  37. * the register MRD is read to obtain the PHY register content.
  38. */
  39. static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
  40. {
  41. u32 rc;
  42. int ret;
  43. struct axienet_local *lp = bus->priv;
  44. ret = axienet_mdio_wait_until_ready(lp);
  45. if (ret < 0)
  46. return ret;
  47. axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
  48. (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
  49. XAE_MDIO_MCR_PHYAD_MASK) |
  50. ((reg << XAE_MDIO_MCR_REGAD_SHIFT) &
  51. XAE_MDIO_MCR_REGAD_MASK) |
  52. XAE_MDIO_MCR_INITIATE_MASK |
  53. XAE_MDIO_MCR_OP_READ_MASK));
  54. ret = axienet_mdio_wait_until_ready(lp);
  55. if (ret < 0)
  56. return ret;
  57. rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF;
  58. dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n",
  59. phy_id, reg, rc);
  60. return rc;
  61. }
  62. /**
  63. * axienet_mdio_write - MDIO interface write function
  64. * @bus: Pointer to mii bus structure
  65. * @phy_id: Address of the PHY device
  66. * @reg: PHY register to write to
  67. * @val: Value to be written into the register
  68. *
  69. * Return: 0 on success, -ETIMEDOUT on a timeout
  70. *
  71. * Writes the value to the requested register by first writing the value
  72. * into MWD register. The the MCR register is then appropriately setup
  73. * to finish the write operation.
  74. */
  75. static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
  76. u16 val)
  77. {
  78. int ret;
  79. struct axienet_local *lp = bus->priv;
  80. dev_dbg(lp->dev, "axienet_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
  81. phy_id, reg, val);
  82. ret = axienet_mdio_wait_until_ready(lp);
  83. if (ret < 0)
  84. return ret;
  85. axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val);
  86. axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
  87. (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
  88. XAE_MDIO_MCR_PHYAD_MASK) |
  89. ((reg << XAE_MDIO_MCR_REGAD_SHIFT) &
  90. XAE_MDIO_MCR_REGAD_MASK) |
  91. XAE_MDIO_MCR_INITIATE_MASK |
  92. XAE_MDIO_MCR_OP_WRITE_MASK));
  93. ret = axienet_mdio_wait_until_ready(lp);
  94. if (ret < 0)
  95. return ret;
  96. return 0;
  97. }
  98. /**
  99. * axienet_mdio_enable - MDIO hardware setup function
  100. * @lp: Pointer to axienet local data structure.
  101. *
  102. * Return: 0 on success, -ETIMEDOUT on a timeout.
  103. *
  104. * Sets up the MDIO interface by initializing the MDIO clock and enabling the
  105. * MDIO interface in hardware.
  106. **/
  107. int axienet_mdio_enable(struct axienet_local *lp)
  108. {
  109. u32 clk_div, host_clock;
  110. if (lp->clk) {
  111. host_clock = clk_get_rate(lp->clk);
  112. } else {
  113. struct device_node *np1;
  114. /* Legacy fallback: detect CPU clock frequency and use as AXI
  115. * bus clock frequency. This only works on certain platforms.
  116. */
  117. np1 = of_find_node_by_name(NULL, "cpu");
  118. if (!np1) {
  119. netdev_warn(lp->ndev, "Could not find CPU device node.\n");
  120. host_clock = DEFAULT_HOST_CLOCK;
  121. } else {
  122. int ret = of_property_read_u32(np1, "clock-frequency",
  123. &host_clock);
  124. if (ret) {
  125. netdev_warn(lp->ndev, "CPU clock-frequency property not found.\n");
  126. host_clock = DEFAULT_HOST_CLOCK;
  127. }
  128. of_node_put(np1);
  129. }
  130. netdev_info(lp->ndev, "Setting assumed host clock to %u\n",
  131. host_clock);
  132. }
  133. /* clk_div can be calculated by deriving it from the equation:
  134. * fMDIO = fHOST / ((1 + clk_div) * 2)
  135. *
  136. * Where fMDIO <= 2500000, so we get:
  137. * fHOST / ((1 + clk_div) * 2) <= 2500000
  138. *
  139. * Then we get:
  140. * 1 / ((1 + clk_div) * 2) <= (2500000 / fHOST)
  141. *
  142. * Then we get:
  143. * 1 / (1 + clk_div) <= ((2500000 * 2) / fHOST)
  144. *
  145. * Then we get:
  146. * 1 / (1 + clk_div) <= (5000000 / fHOST)
  147. *
  148. * So:
  149. * (1 + clk_div) >= (fHOST / 5000000)
  150. *
  151. * And finally:
  152. * clk_div >= (fHOST / 5000000) - 1
  153. *
  154. * fHOST can be read from the flattened device tree as property
  155. * "clock-frequency" from the CPU
  156. */
  157. clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
  158. /* If there is any remainder from the division of
  159. * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
  160. * 1 to the clock divisor or we will surely be above 2.5 MHz
  161. */
  162. if (host_clock % (MAX_MDIO_FREQ * 2))
  163. clk_div++;
  164. netdev_dbg(lp->ndev,
  165. "Setting MDIO clock divisor to %u/%u Hz host clock.\n",
  166. clk_div, host_clock);
  167. axienet_iow(lp, XAE_MDIO_MC_OFFSET, clk_div | XAE_MDIO_MC_MDIOEN_MASK);
  168. return axienet_mdio_wait_until_ready(lp);
  169. }
  170. /**
  171. * axienet_mdio_disable - MDIO hardware disable function
  172. * @lp: Pointer to axienet local data structure.
  173. *
  174. * Disable the MDIO interface in hardware.
  175. **/
  176. void axienet_mdio_disable(struct axienet_local *lp)
  177. {
  178. axienet_iow(lp, XAE_MDIO_MC_OFFSET, 0);
  179. }
  180. /**
  181. * axienet_mdio_setup - MDIO setup function
  182. * @lp: Pointer to axienet local data structure.
  183. *
  184. * Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
  185. * mdiobus_alloc (to allocate memory for mii bus structure) fails.
  186. *
  187. * Sets up the MDIO interface by initializing the MDIO clock and enabling the
  188. * MDIO interface in hardware. Register the MDIO interface.
  189. **/
  190. int axienet_mdio_setup(struct axienet_local *lp)
  191. {
  192. struct device_node *mdio_node;
  193. struct mii_bus *bus;
  194. int ret;
  195. ret = axienet_mdio_enable(lp);
  196. if (ret < 0)
  197. return ret;
  198. bus = mdiobus_alloc();
  199. if (!bus)
  200. return -ENOMEM;
  201. snprintf(bus->id, MII_BUS_ID_SIZE, "axienet-%.8llx",
  202. (unsigned long long)lp->regs_start);
  203. bus->priv = lp;
  204. bus->name = "Xilinx Axi Ethernet MDIO";
  205. bus->read = axienet_mdio_read;
  206. bus->write = axienet_mdio_write;
  207. bus->parent = lp->dev;
  208. lp->mii_bus = bus;
  209. mdio_node = of_get_child_by_name(lp->dev->of_node, "mdio");
  210. ret = of_mdiobus_register(bus, mdio_node);
  211. of_node_put(mdio_node);
  212. if (ret) {
  213. mdiobus_free(bus);
  214. lp->mii_bus = NULL;
  215. return ret;
  216. }
  217. return 0;
  218. }
  219. /**
  220. * axienet_mdio_teardown - MDIO remove function
  221. * @lp: Pointer to axienet local data structure.
  222. *
  223. * Unregisters the MDIO and frees any associate memory for mii bus.
  224. */
  225. void axienet_mdio_teardown(struct axienet_local *lp)
  226. {
  227. mdiobus_unregister(lp->mii_bus);
  228. mdiobus_free(lp->mii_bus);
  229. lp->mii_bus = NULL;
  230. }