marvell10g.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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 for a setup using single-lane Serdes:
  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. * With XAUI, observation shows:
  16. *
  17. * XAUI PHYXS -- <appropriate PCS as above>
  18. *
  19. * and no switching of the host interface mode occurs.
  20. *
  21. * If both the fiber and copper ports are connected, the first to gain
  22. * link takes priority and the other port is completely locked out.
  23. */
  24. #include <linux/ctype.h>
  25. #include <linux/hwmon.h>
  26. #include <linux/marvell_phy.h>
  27. #include <linux/phy.h>
  28. enum {
  29. MV_PCS_BASE_T = 0x0000,
  30. MV_PCS_BASE_R = 0x1000,
  31. MV_PCS_1000BASEX = 0x2000,
  32. MV_PCS_PAIRSWAP = 0x8182,
  33. MV_PCS_PAIRSWAP_MASK = 0x0003,
  34. MV_PCS_PAIRSWAP_AB = 0x0002,
  35. MV_PCS_PAIRSWAP_NONE = 0x0003,
  36. /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
  37. * registers appear to set themselves to the 0x800X when AN is
  38. * restarted, but status registers appear readable from either.
  39. */
  40. MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */
  41. MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
  42. /* Vendor2 MMD registers */
  43. MV_V2_TEMP_CTRL = 0xf08a,
  44. MV_V2_TEMP_CTRL_MASK = 0xc000,
  45. MV_V2_TEMP_CTRL_SAMPLE = 0x0000,
  46. MV_V2_TEMP_CTRL_DISABLE = 0xc000,
  47. MV_V2_TEMP = 0xf08c,
  48. MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */
  49. };
  50. struct mv3310_priv {
  51. struct device *hwmon_dev;
  52. char *hwmon_name;
  53. };
  54. static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
  55. u16 mask, u16 bits)
  56. {
  57. int old, val, ret;
  58. old = phy_read_mmd(phydev, devad, reg);
  59. if (old < 0)
  60. return old;
  61. val = (old & ~mask) | (bits & mask);
  62. if (val == old)
  63. return 0;
  64. ret = phy_write_mmd(phydev, devad, reg, val);
  65. return ret < 0 ? ret : 1;
  66. }
  67. #ifdef CONFIG_HWMON
  68. static umode_t mv3310_hwmon_is_visible(const void *data,
  69. enum hwmon_sensor_types type,
  70. u32 attr, int channel)
  71. {
  72. if (type == hwmon_chip && attr == hwmon_chip_update_interval)
  73. return 0444;
  74. if (type == hwmon_temp && attr == hwmon_temp_input)
  75. return 0444;
  76. return 0;
  77. }
  78. static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
  79. u32 attr, int channel, long *value)
  80. {
  81. struct phy_device *phydev = dev_get_drvdata(dev);
  82. int temp;
  83. if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
  84. *value = MSEC_PER_SEC;
  85. return 0;
  86. }
  87. if (type == hwmon_temp && attr == hwmon_temp_input) {
  88. temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
  89. if (temp < 0)
  90. return temp;
  91. *value = ((temp & 0xff) - 75) * 1000;
  92. return 0;
  93. }
  94. return -EOPNOTSUPP;
  95. }
  96. static const struct hwmon_ops mv3310_hwmon_ops = {
  97. .is_visible = mv3310_hwmon_is_visible,
  98. .read = mv3310_hwmon_read,
  99. };
  100. static u32 mv3310_hwmon_chip_config[] = {
  101. HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
  102. 0,
  103. };
  104. static const struct hwmon_channel_info mv3310_hwmon_chip = {
  105. .type = hwmon_chip,
  106. .config = mv3310_hwmon_chip_config,
  107. };
  108. static u32 mv3310_hwmon_temp_config[] = {
  109. HWMON_T_INPUT,
  110. 0,
  111. };
  112. static const struct hwmon_channel_info mv3310_hwmon_temp = {
  113. .type = hwmon_temp,
  114. .config = mv3310_hwmon_temp_config,
  115. };
  116. static const struct hwmon_channel_info *mv3310_hwmon_info[] = {
  117. &mv3310_hwmon_chip,
  118. &mv3310_hwmon_temp,
  119. NULL,
  120. };
  121. static const struct hwmon_chip_info mv3310_hwmon_chip_info = {
  122. .ops = &mv3310_hwmon_ops,
  123. .info = mv3310_hwmon_info,
  124. };
  125. static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
  126. {
  127. u16 val;
  128. int ret;
  129. ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
  130. MV_V2_TEMP_UNKNOWN);
  131. if (ret < 0)
  132. return ret;
  133. val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
  134. ret = mv3310_modify(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
  135. MV_V2_TEMP_CTRL_MASK, val);
  136. return ret < 0 ? ret : 0;
  137. }
  138. static void mv3310_hwmon_disable(void *data)
  139. {
  140. struct phy_device *phydev = data;
  141. mv3310_hwmon_config(phydev, false);
  142. }
  143. static int mv3310_hwmon_probe(struct phy_device *phydev)
  144. {
  145. struct device *dev = &phydev->mdio.dev;
  146. struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
  147. int i, j, ret;
  148. priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
  149. if (!priv->hwmon_name)
  150. return -ENODEV;
  151. for (i = j = 0; priv->hwmon_name[i]; i++) {
  152. if (isalnum(priv->hwmon_name[i])) {
  153. if (i != j)
  154. priv->hwmon_name[j] = priv->hwmon_name[i];
  155. j++;
  156. }
  157. }
  158. priv->hwmon_name[j] = '\0';
  159. ret = mv3310_hwmon_config(phydev, true);
  160. if (ret)
  161. return ret;
  162. ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
  163. if (ret)
  164. return ret;
  165. priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
  166. priv->hwmon_name, phydev,
  167. &mv3310_hwmon_chip_info, NULL);
  168. return PTR_ERR_OR_ZERO(priv->hwmon_dev);
  169. }
  170. #else
  171. static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
  172. {
  173. return 0;
  174. }
  175. static int mv3310_hwmon_probe(struct phy_device *phydev)
  176. {
  177. return 0;
  178. }
  179. #endif
  180. static int mv3310_probe(struct phy_device *phydev)
  181. {
  182. struct mv3310_priv *priv;
  183. u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
  184. int ret;
  185. if (!phydev->is_c45 ||
  186. (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
  187. return -ENODEV;
  188. priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
  189. if (!priv)
  190. return -ENOMEM;
  191. dev_set_drvdata(&phydev->mdio.dev, priv);
  192. ret = mv3310_hwmon_probe(phydev);
  193. if (ret)
  194. return ret;
  195. return 0;
  196. }
  197. static int mv3310_suspend(struct phy_device *phydev)
  198. {
  199. return 0;
  200. }
  201. static int mv3310_resume(struct phy_device *phydev)
  202. {
  203. return mv3310_hwmon_config(phydev, true);
  204. }
  205. static int mv3310_config_init(struct phy_device *phydev)
  206. {
  207. __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
  208. u32 mask;
  209. int val;
  210. /* Check that the PHY interface type is compatible */
  211. if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
  212. phydev->interface != PHY_INTERFACE_MODE_XAUI &&
  213. phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
  214. phydev->interface != PHY_INTERFACE_MODE_10GKR)
  215. return -ENODEV;
  216. __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
  217. __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
  218. if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
  219. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
  220. if (val < 0)
  221. return val;
  222. if (val & MDIO_AN_STAT1_ABLE)
  223. __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
  224. }
  225. val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
  226. if (val < 0)
  227. return val;
  228. /* Ethtool does not support the WAN mode bits */
  229. if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
  230. MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
  231. MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
  232. MDIO_PMA_STAT2_10GBEW))
  233. __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
  234. if (val & MDIO_PMA_STAT2_10GBSR)
  235. __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
  236. if (val & MDIO_PMA_STAT2_10GBLR)
  237. __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
  238. if (val & MDIO_PMA_STAT2_10GBER)
  239. __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
  240. if (val & MDIO_PMA_STAT2_EXTABLE) {
  241. val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
  242. if (val < 0)
  243. return val;
  244. if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
  245. MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
  246. __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
  247. if (val & MDIO_PMA_EXTABLE_10GBLRM)
  248. __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
  249. if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
  250. MDIO_PMA_EXTABLE_1000BKX))
  251. __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
  252. if (val & MDIO_PMA_EXTABLE_10GBLRM)
  253. __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
  254. supported);
  255. if (val & MDIO_PMA_EXTABLE_10GBT)
  256. __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
  257. supported);
  258. if (val & MDIO_PMA_EXTABLE_10GBKX4)
  259. __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
  260. supported);
  261. if (val & MDIO_PMA_EXTABLE_10GBKR)
  262. __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
  263. supported);
  264. if (val & MDIO_PMA_EXTABLE_1000BT)
  265. __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
  266. supported);
  267. if (val & MDIO_PMA_EXTABLE_1000BKX)
  268. __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
  269. supported);
  270. if (val & MDIO_PMA_EXTABLE_100BTX) {
  271. __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
  272. supported);
  273. __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
  274. supported);
  275. }
  276. if (val & MDIO_PMA_EXTABLE_10BT) {
  277. __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
  278. supported);
  279. __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
  280. supported);
  281. }
  282. }
  283. if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
  284. dev_warn(&phydev->mdio.dev,
  285. "PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
  286. __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
  287. phydev->supported &= mask;
  288. phydev->advertising &= phydev->supported;
  289. return 0;
  290. }
  291. static int mv3310_config_aneg(struct phy_device *phydev)
  292. {
  293. bool changed = false;
  294. u32 advertising;
  295. int ret;
  296. /* We don't support manual MDI control */
  297. phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
  298. if (phydev->autoneg == AUTONEG_DISABLE) {
  299. ret = genphy_c45_pma_setup_forced(phydev);
  300. if (ret < 0)
  301. return ret;
  302. return genphy_c45_an_disable_aneg(phydev);
  303. }
  304. phydev->advertising &= phydev->supported;
  305. advertising = phydev->advertising;
  306. ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
  307. ADVERTISE_ALL | ADVERTISE_100BASE4 |
  308. ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
  309. ethtool_adv_to_mii_adv_t(advertising));
  310. if (ret < 0)
  311. return ret;
  312. if (ret > 0)
  313. changed = true;
  314. ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
  315. ADVERTISE_1000FULL | ADVERTISE_1000HALF,
  316. ethtool_adv_to_mii_ctrl1000_t(advertising));
  317. if (ret < 0)
  318. return ret;
  319. if (ret > 0)
  320. changed = true;
  321. /* 10G control register */
  322. ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
  323. MDIO_AN_10GBT_CTRL_ADV10G,
  324. advertising & ADVERTISED_10000baseT_Full ?
  325. MDIO_AN_10GBT_CTRL_ADV10G : 0);
  326. if (ret < 0)
  327. return ret;
  328. if (ret > 0)
  329. changed = true;
  330. if (changed)
  331. ret = genphy_c45_restart_aneg(phydev);
  332. return ret;
  333. }
  334. static int mv3310_aneg_done(struct phy_device *phydev)
  335. {
  336. int val;
  337. val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
  338. if (val < 0)
  339. return val;
  340. if (val & MDIO_STAT1_LSTATUS)
  341. return 1;
  342. return genphy_c45_aneg_done(phydev);
  343. }
  344. static void mv3310_update_interface(struct phy_device *phydev)
  345. {
  346. if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
  347. phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
  348. /* The PHY automatically switches its serdes interface (and
  349. * active PHYXS instance) between Cisco SGMII and 10GBase-KR
  350. * modes according to the speed. Florian suggests setting
  351. * phydev->interface to communicate this to the MAC. Only do
  352. * this if we are already in either SGMII or 10GBase-KR mode.
  353. */
  354. if (phydev->speed == SPEED_10000)
  355. phydev->interface = PHY_INTERFACE_MODE_10GKR;
  356. else if (phydev->speed >= SPEED_10 &&
  357. phydev->speed < SPEED_10000)
  358. phydev->interface = PHY_INTERFACE_MODE_SGMII;
  359. }
  360. }
  361. /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
  362. static int mv3310_read_10gbr_status(struct phy_device *phydev)
  363. {
  364. phydev->link = 1;
  365. phydev->speed = SPEED_10000;
  366. phydev->duplex = DUPLEX_FULL;
  367. mv3310_update_interface(phydev);
  368. return 0;
  369. }
  370. static int mv3310_read_status(struct phy_device *phydev)
  371. {
  372. u32 mmd_mask = phydev->c45_ids.devices_in_package;
  373. int val;
  374. /* The vendor devads do not report link status. Avoid the PHYXS
  375. * instance as there are three, and its status depends on the MAC
  376. * being appropriately configured for the negotiated speed.
  377. */
  378. mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
  379. BIT(MDIO_MMD_PHYXS));
  380. phydev->speed = SPEED_UNKNOWN;
  381. phydev->duplex = DUPLEX_UNKNOWN;
  382. phydev->lp_advertising = 0;
  383. phydev->link = 0;
  384. phydev->pause = 0;
  385. phydev->asym_pause = 0;
  386. phydev->mdix = 0;
  387. val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
  388. if (val < 0)
  389. return val;
  390. if (val & MDIO_STAT1_LSTATUS)
  391. return mv3310_read_10gbr_status(phydev);
  392. val = genphy_c45_read_link(phydev, mmd_mask);
  393. if (val < 0)
  394. return val;
  395. phydev->link = val > 0 ? 1 : 0;
  396. val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
  397. if (val < 0)
  398. return val;
  399. if (val & MDIO_AN_STAT1_COMPLETE) {
  400. val = genphy_c45_read_lpa(phydev);
  401. if (val < 0)
  402. return val;
  403. /* Read the link partner's 1G advertisement */
  404. val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
  405. if (val < 0)
  406. return val;
  407. phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
  408. if (phydev->autoneg == AUTONEG_ENABLE)
  409. phy_resolve_aneg_linkmode(phydev);
  410. }
  411. if (phydev->autoneg != AUTONEG_ENABLE) {
  412. val = genphy_c45_read_pma(phydev);
  413. if (val < 0)
  414. return val;
  415. }
  416. if (phydev->speed == SPEED_10000) {
  417. val = genphy_c45_read_mdix(phydev);
  418. if (val < 0)
  419. return val;
  420. } else {
  421. val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PAIRSWAP);
  422. if (val < 0)
  423. return val;
  424. switch (val & MV_PCS_PAIRSWAP_MASK) {
  425. case MV_PCS_PAIRSWAP_AB:
  426. phydev->mdix = ETH_TP_MDI_X;
  427. break;
  428. case MV_PCS_PAIRSWAP_NONE:
  429. phydev->mdix = ETH_TP_MDI;
  430. break;
  431. default:
  432. phydev->mdix = ETH_TP_MDI_INVALID;
  433. break;
  434. }
  435. }
  436. mv3310_update_interface(phydev);
  437. return 0;
  438. }
  439. static struct phy_driver mv3310_drivers[] = {
  440. {
  441. .phy_id = 0x002b09aa,
  442. .phy_id_mask = MARVELL_PHY_ID_MASK,
  443. .name = "mv88x3310",
  444. .features = SUPPORTED_10baseT_Full |
  445. SUPPORTED_10baseT_Half |
  446. SUPPORTED_100baseT_Full |
  447. SUPPORTED_100baseT_Half |
  448. SUPPORTED_1000baseT_Full |
  449. SUPPORTED_Autoneg |
  450. SUPPORTED_TP |
  451. SUPPORTED_FIBRE |
  452. SUPPORTED_10000baseT_Full |
  453. SUPPORTED_Backplane,
  454. .soft_reset = gen10g_no_soft_reset,
  455. .config_init = mv3310_config_init,
  456. .probe = mv3310_probe,
  457. .suspend = mv3310_suspend,
  458. .resume = mv3310_resume,
  459. .config_aneg = mv3310_config_aneg,
  460. .aneg_done = mv3310_aneg_done,
  461. .read_status = mv3310_read_status,
  462. },
  463. };
  464. module_phy_driver(mv3310_drivers);
  465. static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
  466. { 0x002b09aa, MARVELL_PHY_ID_MASK },
  467. { },
  468. };
  469. MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
  470. MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
  471. MODULE_LICENSE("GPL");