phy-c45.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * Clause 45 PHY support
  3. */
  4. #include <linux/ethtool.h>
  5. #include <linux/export.h>
  6. #include <linux/mdio.h>
  7. #include <linux/mii.h>
  8. #include <linux/phy.h>
  9. /**
  10. * genphy_c45_setup_forced - configures a forced speed
  11. * @phydev: target phy_device struct
  12. */
  13. int genphy_c45_pma_setup_forced(struct phy_device *phydev)
  14. {
  15. int ctrl1, ctrl2, ret;
  16. /* Half duplex is not supported */
  17. if (phydev->duplex != DUPLEX_FULL)
  18. return -EINVAL;
  19. ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
  20. if (ctrl1 < 0)
  21. return ctrl1;
  22. ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
  23. if (ctrl2 < 0)
  24. return ctrl2;
  25. ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
  26. /*
  27. * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0. See 45.2.1.6.1
  28. * in 802.3-2012 and 802.3-2015.
  29. */
  30. ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
  31. switch (phydev->speed) {
  32. case SPEED_10:
  33. ctrl2 |= MDIO_PMA_CTRL2_10BT;
  34. break;
  35. case SPEED_100:
  36. ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
  37. ctrl2 |= MDIO_PMA_CTRL2_100BTX;
  38. break;
  39. case SPEED_1000:
  40. ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
  41. /* Assume 1000base-T */
  42. ctrl2 |= MDIO_PMA_CTRL2_1000BT;
  43. break;
  44. case SPEED_10000:
  45. ctrl1 |= MDIO_CTRL1_SPEED10G;
  46. /* Assume 10Gbase-T */
  47. ctrl2 |= MDIO_PMA_CTRL2_10GBT;
  48. break;
  49. default:
  50. return -EINVAL;
  51. }
  52. ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
  53. if (ret < 0)
  54. return ret;
  55. return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
  56. }
  57. EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
  58. /**
  59. * genphy_c45_an_disable_aneg - disable auto-negotiation
  60. * @phydev: target phy_device struct
  61. *
  62. * Disable auto-negotiation in the Clause 45 PHY. The link parameters
  63. * parameters are controlled through the PMA/PMD MMD registers.
  64. *
  65. * Returns zero on success, negative errno code on failure.
  66. */
  67. int genphy_c45_an_disable_aneg(struct phy_device *phydev)
  68. {
  69. int val;
  70. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
  71. if (val < 0)
  72. return val;
  73. val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
  74. return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
  75. }
  76. EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
  77. /**
  78. * genphy_c45_restart_aneg - Enable and restart auto-negotiation
  79. * @phydev: target phy_device struct
  80. *
  81. * This assumes that the auto-negotiation MMD is present.
  82. *
  83. * Enable and restart auto-negotiation.
  84. */
  85. int genphy_c45_restart_aneg(struct phy_device *phydev)
  86. {
  87. int val;
  88. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
  89. if (val < 0)
  90. return val;
  91. val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
  92. return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
  93. }
  94. EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
  95. /**
  96. * genphy_c45_aneg_done - return auto-negotiation complete status
  97. * @phydev: target phy_device struct
  98. *
  99. * This assumes that the auto-negotiation MMD is present.
  100. *
  101. * Reads the status register from the auto-negotiation MMD, returning:
  102. * - positive if auto-negotiation is complete
  103. * - negative errno code on error
  104. * - zero otherwise
  105. */
  106. int genphy_c45_aneg_done(struct phy_device *phydev)
  107. {
  108. int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
  109. return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
  110. }
  111. EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
  112. /**
  113. * genphy_c45_read_link - read the overall link status from the MMDs
  114. * @phydev: target phy_device struct
  115. * @mmd_mask: MMDs to read status from
  116. *
  117. * Read the link status from the specified MMDs, and if they all indicate
  118. * that the link is up, return positive. If an error is encountered,
  119. * a negative errno will be returned, otherwise zero.
  120. */
  121. int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
  122. {
  123. int val, devad;
  124. bool link = true;
  125. while (mmd_mask) {
  126. devad = __ffs(mmd_mask);
  127. mmd_mask &= ~BIT(devad);
  128. /* The link state is latched low so that momentary link
  129. * drops can be detected. Do not double-read the status
  130. * in polling mode to detect such short link drops.
  131. */
  132. if (!phy_polling_mode(phydev)) {
  133. val = phy_read_mmd(phydev, devad, MDIO_STAT1);
  134. if (val < 0)
  135. return val;
  136. }
  137. val = phy_read_mmd(phydev, devad, MDIO_STAT1);
  138. if (val < 0)
  139. return val;
  140. if (!(val & MDIO_STAT1_LSTATUS))
  141. link = false;
  142. }
  143. return link;
  144. }
  145. EXPORT_SYMBOL_GPL(genphy_c45_read_link);
  146. /**
  147. * genphy_c45_read_lpa - read the link partner advertisement and pause
  148. * @phydev: target phy_device struct
  149. *
  150. * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
  151. * filling in the link partner advertisement, pause and asym_pause members
  152. * in @phydev. This assumes that the auto-negotiation MMD is present, and
  153. * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected
  154. * to fill in the remainder of the link partner advert from vendor registers.
  155. */
  156. int genphy_c45_read_lpa(struct phy_device *phydev)
  157. {
  158. int val;
  159. /* Read the link partner's base page advertisement */
  160. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
  161. if (val < 0)
  162. return val;
  163. phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(val);
  164. phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
  165. phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
  166. /* Read the link partner's 10G advertisement */
  167. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
  168. if (val < 0)
  169. return val;
  170. if (val & MDIO_AN_10GBT_STAT_LP10G)
  171. phydev->lp_advertising |= ADVERTISED_10000baseT_Full;
  172. return 0;
  173. }
  174. EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
  175. /**
  176. * genphy_c45_read_pma - read link speed etc from PMA
  177. * @phydev: target phy_device struct
  178. */
  179. int genphy_c45_read_pma(struct phy_device *phydev)
  180. {
  181. int val;
  182. val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
  183. if (val < 0)
  184. return val;
  185. switch (val & MDIO_CTRL1_SPEEDSEL) {
  186. case 0:
  187. phydev->speed = SPEED_10;
  188. break;
  189. case MDIO_PMA_CTRL1_SPEED100:
  190. phydev->speed = SPEED_100;
  191. break;
  192. case MDIO_PMA_CTRL1_SPEED1000:
  193. phydev->speed = SPEED_1000;
  194. break;
  195. case MDIO_CTRL1_SPEED10G:
  196. phydev->speed = SPEED_10000;
  197. break;
  198. default:
  199. phydev->speed = SPEED_UNKNOWN;
  200. break;
  201. }
  202. phydev->duplex = DUPLEX_FULL;
  203. return 0;
  204. }
  205. EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
  206. /**
  207. * genphy_c45_read_mdix - read mdix status from PMA
  208. * @phydev: target phy_device struct
  209. */
  210. int genphy_c45_read_mdix(struct phy_device *phydev)
  211. {
  212. int val;
  213. if (phydev->speed == SPEED_10000) {
  214. val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
  215. MDIO_PMA_10GBT_SWAPPOL);
  216. if (val < 0)
  217. return val;
  218. switch (val) {
  219. case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
  220. phydev->mdix = ETH_TP_MDI;
  221. break;
  222. case 0:
  223. phydev->mdix = ETH_TP_MDI_X;
  224. break;
  225. default:
  226. phydev->mdix = ETH_TP_MDI_INVALID;
  227. break;
  228. }
  229. }
  230. return 0;
  231. }
  232. EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
  233. /* The gen10g_* functions are the old Clause 45 stub */
  234. int gen10g_config_aneg(struct phy_device *phydev)
  235. {
  236. return 0;
  237. }
  238. EXPORT_SYMBOL_GPL(gen10g_config_aneg);
  239. int gen10g_read_status(struct phy_device *phydev)
  240. {
  241. u32 mmd_mask = phydev->c45_ids.devices_in_package;
  242. int ret;
  243. /* For now just lie and say it's 10G all the time */
  244. phydev->speed = SPEED_10000;
  245. phydev->duplex = DUPLEX_FULL;
  246. /* Avoid reading the vendor MMDs */
  247. mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
  248. ret = genphy_c45_read_link(phydev, mmd_mask);
  249. phydev->link = ret > 0 ? 1 : 0;
  250. return 0;
  251. }
  252. EXPORT_SYMBOL_GPL(gen10g_read_status);
  253. int gen10g_no_soft_reset(struct phy_device *phydev)
  254. {
  255. /* Do nothing for now */
  256. return 0;
  257. }
  258. EXPORT_SYMBOL_GPL(gen10g_no_soft_reset);
  259. int gen10g_config_init(struct phy_device *phydev)
  260. {
  261. /* Temporarily just say we support everything */
  262. phydev->supported = SUPPORTED_10000baseT_Full;
  263. phydev->advertising = SUPPORTED_10000baseT_Full;
  264. return 0;
  265. }
  266. EXPORT_SYMBOL_GPL(gen10g_config_init);
  267. int gen10g_suspend(struct phy_device *phydev)
  268. {
  269. return 0;
  270. }
  271. EXPORT_SYMBOL_GPL(gen10g_suspend);
  272. int gen10g_resume(struct phy_device *phydev)
  273. {
  274. return 0;
  275. }
  276. EXPORT_SYMBOL_GPL(gen10g_resume);
  277. struct phy_driver genphy_10g_driver = {
  278. .phy_id = 0xffffffff,
  279. .phy_id_mask = 0xffffffff,
  280. .name = "Generic 10G PHY",
  281. .soft_reset = gen10g_no_soft_reset,
  282. .config_init = gen10g_config_init,
  283. .features = 0,
  284. .config_aneg = gen10g_config_aneg,
  285. .read_status = gen10g_read_status,
  286. .suspend = gen10g_suspend,
  287. .resume = gen10g_resume,
  288. };