marvell10g.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Marvell 10G 88x3310 PHY driver
  3. *
  4. * Based upon the ID registers, this PHY appears to be a mixture of IPs
  5. * from two different companies.
  6. *
  7. * There appears to be several different data paths through the PHY which
  8. * are automatically managed by the PHY. The following has been determined
  9. * via observation and experimentation:
  10. *
  11. * SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
  12. * 10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
  13. * 10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
  14. *
  15. * If both the fiber and copper ports are connected, the first to gain
  16. * link takes priority and the other port is completely locked out.
  17. */
  18. #include <linux/phy.h>
  19. enum {
  20. MV_PCS_BASE_T = 0x0000,
  21. MV_PCS_BASE_R = 0x1000,
  22. MV_PCS_1000BASEX = 0x2000,
  23. /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
  24. * registers appear to set themselves to the 0x800X when AN is
  25. * restarted, but status registers appear readable from either.
  26. */
  27. MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */
  28. MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
  29. /* This register appears to reflect the copper status */
  30. MV_AN_RESULT = 0xa016,
  31. MV_AN_RESULT_SPD_10 = BIT(12),
  32. MV_AN_RESULT_SPD_100 = BIT(13),
  33. MV_AN_RESULT_SPD_1000 = BIT(14),
  34. MV_AN_RESULT_SPD_10000 = BIT(15),
  35. };
  36. static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
  37. u16 mask, u16 bits)
  38. {
  39. int old, val, ret;
  40. old = phy_read_mmd(phydev, devad, reg);
  41. if (old < 0)
  42. return old;
  43. val = (old & ~mask) | (bits & mask);
  44. if (val == old)
  45. return 0;
  46. ret = phy_write_mmd(phydev, devad, reg, val);
  47. return ret < 0 ? ret : 1;
  48. }
  49. static int mv3310_probe(struct phy_device *phydev)
  50. {
  51. u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
  52. if (!phydev->is_c45 ||
  53. (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
  54. return -ENODEV;
  55. return 0;
  56. }
  57. /*
  58. * Resetting the MV88X3310 causes it to become non-responsive. Avoid
  59. * setting the reset bit(s).
  60. */
  61. static int mv3310_soft_reset(struct phy_device *phydev)
  62. {
  63. return 0;
  64. }
  65. static int mv3310_config_init(struct phy_device *phydev)
  66. {
  67. __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
  68. u32 mask;
  69. int val;
  70. /* Check that the PHY interface type is compatible */
  71. if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
  72. phydev->interface != PHY_INTERFACE_MODE_XGMII &&
  73. phydev->interface != PHY_INTERFACE_MODE_XAUI &&
  74. phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
  75. phydev->interface != PHY_INTERFACE_MODE_10GKR)
  76. return -ENODEV;
  77. __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
  78. __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
  79. if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
  80. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
  81. if (val < 0)
  82. return val;
  83. if (val & MDIO_AN_STAT1_ABLE)
  84. __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
  85. }
  86. val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
  87. if (val < 0)
  88. return val;
  89. /* Ethtool does not support the WAN mode bits */
  90. if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
  91. MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
  92. MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
  93. MDIO_PMA_STAT2_10GBEW))
  94. __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
  95. if (val & MDIO_PMA_STAT2_10GBSR)
  96. __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
  97. if (val & MDIO_PMA_STAT2_10GBLR)
  98. __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
  99. if (val & MDIO_PMA_STAT2_10GBER)
  100. __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
  101. if (val & MDIO_PMA_STAT2_EXTABLE) {
  102. val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
  103. if (val < 0)
  104. return val;
  105. if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
  106. MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
  107. __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
  108. if (val & MDIO_PMA_EXTABLE_10GBLRM)
  109. __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
  110. if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
  111. MDIO_PMA_EXTABLE_1000BKX))
  112. __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
  113. if (val & MDIO_PMA_EXTABLE_10GBLRM)
  114. __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
  115. supported);
  116. if (val & MDIO_PMA_EXTABLE_10GBT)
  117. __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
  118. supported);
  119. if (val & MDIO_PMA_EXTABLE_10GBKX4)
  120. __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
  121. supported);
  122. if (val & MDIO_PMA_EXTABLE_10GBKR)
  123. __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
  124. supported);
  125. if (val & MDIO_PMA_EXTABLE_1000BT)
  126. __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
  127. supported);
  128. if (val & MDIO_PMA_EXTABLE_1000BKX)
  129. __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
  130. supported);
  131. if (val & MDIO_PMA_EXTABLE_100BTX)
  132. __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
  133. supported);
  134. if (val & MDIO_PMA_EXTABLE_10BT)
  135. __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
  136. supported);
  137. }
  138. if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
  139. dev_warn(&phydev->mdio.dev,
  140. "PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
  141. __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
  142. phydev->supported &= mask;
  143. phydev->advertising &= phydev->supported;
  144. return 0;
  145. }
  146. static int mv3310_config_aneg(struct phy_device *phydev)
  147. {
  148. bool changed = false;
  149. u32 advertising;
  150. int ret;
  151. if (phydev->autoneg == AUTONEG_DISABLE) {
  152. ret = genphy_c45_pma_setup_forced(phydev);
  153. if (ret < 0)
  154. return ret;
  155. return genphy_c45_an_disable_aneg(phydev);
  156. }
  157. phydev->advertising &= phydev->supported;
  158. advertising = phydev->advertising;
  159. ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
  160. ADVERTISE_ALL | ADVERTISE_100BASE4 |
  161. ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
  162. ethtool_adv_to_mii_adv_t(advertising));
  163. if (ret < 0)
  164. return ret;
  165. if (ret > 0)
  166. changed = true;
  167. ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
  168. ADVERTISE_1000FULL | ADVERTISE_1000HALF,
  169. ethtool_adv_to_mii_ctrl1000_t(advertising));
  170. if (ret < 0)
  171. return ret;
  172. if (ret > 0)
  173. changed = true;
  174. /* 10G control register */
  175. ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
  176. MDIO_AN_10GBT_CTRL_ADV10G,
  177. advertising & ADVERTISED_10000baseT_Full ?
  178. MDIO_AN_10GBT_CTRL_ADV10G : 0);
  179. if (ret < 0)
  180. return ret;
  181. if (ret > 0)
  182. changed = true;
  183. if (changed)
  184. ret = genphy_c45_restart_aneg(phydev);
  185. return ret;
  186. }
  187. static int mv3310_aneg_done(struct phy_device *phydev)
  188. {
  189. int val;
  190. val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
  191. if (val < 0)
  192. return val;
  193. if (val & MDIO_STAT1_LSTATUS)
  194. return 1;
  195. return genphy_c45_aneg_done(phydev);
  196. }
  197. /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
  198. static int mv3310_read_10gbr_status(struct phy_device *phydev)
  199. {
  200. phydev->link = 1;
  201. phydev->speed = SPEED_10000;
  202. phydev->duplex = DUPLEX_FULL;
  203. if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
  204. phydev->interface = PHY_INTERFACE_MODE_10GKR;
  205. return 0;
  206. }
  207. static int mv3310_read_status(struct phy_device *phydev)
  208. {
  209. u32 mmd_mask = phydev->c45_ids.devices_in_package;
  210. int val;
  211. /* The vendor devads do not report link status. Avoid the PHYXS
  212. * instance as there are three, and its status depends on the MAC
  213. * being appropriately configured for the negotiated speed.
  214. */
  215. mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
  216. BIT(MDIO_MMD_PHYXS));
  217. phydev->speed = SPEED_UNKNOWN;
  218. phydev->duplex = DUPLEX_UNKNOWN;
  219. phydev->lp_advertising = 0;
  220. phydev->link = 0;
  221. phydev->pause = 0;
  222. phydev->asym_pause = 0;
  223. val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
  224. if (val < 0)
  225. return val;
  226. if (val & MDIO_STAT1_LSTATUS)
  227. return mv3310_read_10gbr_status(phydev);
  228. val = genphy_c45_read_link(phydev, mmd_mask);
  229. if (val < 0)
  230. return val;
  231. phydev->link = val > 0 ? 1 : 0;
  232. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
  233. if (val < 0)
  234. return val;
  235. if (val & MDIO_AN_STAT1_COMPLETE) {
  236. val = genphy_c45_read_lpa(phydev);
  237. if (val < 0)
  238. return val;
  239. /* Read the link partner's 1G advertisment */
  240. val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
  241. if (val < 0)
  242. return val;
  243. phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
  244. if (phydev->autoneg == AUTONEG_ENABLE) {
  245. val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_RESULT);
  246. if (val < 0)
  247. return val;
  248. if (val & MV_AN_RESULT_SPD_10000)
  249. phydev->speed = SPEED_10000;
  250. else if (val & MV_AN_RESULT_SPD_1000)
  251. phydev->speed = SPEED_1000;
  252. else if (val & MV_AN_RESULT_SPD_100)
  253. phydev->speed = SPEED_100;
  254. else if (val & MV_AN_RESULT_SPD_10)
  255. phydev->speed = SPEED_10;
  256. phydev->duplex = DUPLEX_FULL;
  257. }
  258. }
  259. if (phydev->autoneg != AUTONEG_ENABLE) {
  260. val = genphy_c45_read_pma(phydev);
  261. if (val < 0)
  262. return val;
  263. }
  264. if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
  265. phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
  266. /* The PHY automatically switches its serdes interface (and
  267. * active PHYXS instance) between Cisco SGMII and 10GBase-KR
  268. * modes according to the speed. Florian suggests setting
  269. * phydev->interface to communicate this to the MAC. Only do
  270. * this if we are already in either SGMII or 10GBase-KR mode.
  271. */
  272. if (phydev->speed == SPEED_10000)
  273. phydev->interface = PHY_INTERFACE_MODE_10GKR;
  274. else if (phydev->speed >= SPEED_10 &&
  275. phydev->speed < SPEED_10000)
  276. phydev->interface = PHY_INTERFACE_MODE_SGMII;
  277. }
  278. return 0;
  279. }
  280. static struct phy_driver mv3310_drivers[] = {
  281. {
  282. .phy_id = 0x002b09aa,
  283. .phy_id_mask = 0xffffffff,
  284. .name = "mv88x3310",
  285. .features = SUPPORTED_10baseT_Full |
  286. SUPPORTED_100baseT_Full |
  287. SUPPORTED_1000baseT_Full |
  288. SUPPORTED_Autoneg |
  289. SUPPORTED_TP |
  290. SUPPORTED_FIBRE |
  291. SUPPORTED_10000baseT_Full |
  292. SUPPORTED_Backplane,
  293. .probe = mv3310_probe,
  294. .soft_reset = mv3310_soft_reset,
  295. .config_init = mv3310_config_init,
  296. .config_aneg = mv3310_config_aneg,
  297. .aneg_done = mv3310_aneg_done,
  298. .read_status = mv3310_read_status,
  299. },
  300. };
  301. module_phy_driver(mv3310_drivers);
  302. static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
  303. { 0x002b09aa, 0xffffffff },
  304. { },
  305. };
  306. MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
  307. MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
  308. MODULE_LICENSE("GPL");