pcs-xpcs.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2020 Synopsys, Inc. and/or its affiliates.
  4. * Synopsys DesignWare XPCS helpers
  5. *
  6. * Author: Jose Abreu <[email protected]>
  7. */
  8. #include <linux/delay.h>
  9. #include <linux/pcs/pcs-xpcs.h>
  10. #include <linux/mdio.h>
  11. #include <linux/phylink.h>
  12. #include <linux/workqueue.h>
  13. #include "pcs-xpcs.h"
  14. #define phylink_pcs_to_xpcs(pl_pcs) \
  15. container_of((pl_pcs), struct dw_xpcs, pcs)
  16. static const int xpcs_usxgmii_features[] = {
  17. ETHTOOL_LINK_MODE_Pause_BIT,
  18. ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  19. ETHTOOL_LINK_MODE_Autoneg_BIT,
  20. ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
  21. ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
  22. ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
  23. ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
  24. __ETHTOOL_LINK_MODE_MASK_NBITS,
  25. };
  26. static const int xpcs_10gkr_features[] = {
  27. ETHTOOL_LINK_MODE_Pause_BIT,
  28. ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  29. ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
  30. __ETHTOOL_LINK_MODE_MASK_NBITS,
  31. };
  32. static const int xpcs_xlgmii_features[] = {
  33. ETHTOOL_LINK_MODE_Pause_BIT,
  34. ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  35. ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
  36. ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
  37. ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
  38. ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
  39. ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
  40. ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
  41. ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
  42. ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
  43. ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
  44. ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
  45. ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
  46. ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
  47. ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
  48. ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
  49. ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
  50. ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
  51. ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
  52. ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
  53. ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
  54. ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
  55. ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
  56. ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
  57. ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
  58. ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
  59. __ETHTOOL_LINK_MODE_MASK_NBITS,
  60. };
  61. static const int xpcs_sgmii_features[] = {
  62. ETHTOOL_LINK_MODE_Pause_BIT,
  63. ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  64. ETHTOOL_LINK_MODE_Autoneg_BIT,
  65. ETHTOOL_LINK_MODE_10baseT_Half_BIT,
  66. ETHTOOL_LINK_MODE_10baseT_Full_BIT,
  67. ETHTOOL_LINK_MODE_100baseT_Half_BIT,
  68. ETHTOOL_LINK_MODE_100baseT_Full_BIT,
  69. ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
  70. ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
  71. __ETHTOOL_LINK_MODE_MASK_NBITS,
  72. };
  73. static const int xpcs_1000basex_features[] = {
  74. ETHTOOL_LINK_MODE_Pause_BIT,
  75. ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  76. ETHTOOL_LINK_MODE_Autoneg_BIT,
  77. ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
  78. __ETHTOOL_LINK_MODE_MASK_NBITS,
  79. };
  80. static const int xpcs_2500basex_features[] = {
  81. ETHTOOL_LINK_MODE_Pause_BIT,
  82. ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  83. ETHTOOL_LINK_MODE_Autoneg_BIT,
  84. ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
  85. ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
  86. __ETHTOOL_LINK_MODE_MASK_NBITS,
  87. };
  88. static const phy_interface_t xpcs_usxgmii_interfaces[] = {
  89. PHY_INTERFACE_MODE_USXGMII,
  90. };
  91. static const phy_interface_t xpcs_10gkr_interfaces[] = {
  92. PHY_INTERFACE_MODE_10GKR,
  93. };
  94. static const phy_interface_t xpcs_xlgmii_interfaces[] = {
  95. PHY_INTERFACE_MODE_XLGMII,
  96. };
  97. static const phy_interface_t xpcs_sgmii_interfaces[] = {
  98. PHY_INTERFACE_MODE_SGMII,
  99. };
  100. static const phy_interface_t xpcs_1000basex_interfaces[] = {
  101. PHY_INTERFACE_MODE_1000BASEX,
  102. };
  103. static const phy_interface_t xpcs_2500basex_interfaces[] = {
  104. PHY_INTERFACE_MODE_2500BASEX,
  105. PHY_INTERFACE_MODE_MAX,
  106. };
  107. enum {
  108. DW_XPCS_USXGMII,
  109. DW_XPCS_10GKR,
  110. DW_XPCS_XLGMII,
  111. DW_XPCS_SGMII,
  112. DW_XPCS_1000BASEX,
  113. DW_XPCS_2500BASEX,
  114. DW_XPCS_INTERFACE_MAX,
  115. };
  116. struct xpcs_compat {
  117. const int *supported;
  118. const phy_interface_t *interface;
  119. int num_interfaces;
  120. int an_mode;
  121. int (*pma_config)(struct dw_xpcs *xpcs);
  122. };
  123. struct xpcs_id {
  124. u32 id;
  125. u32 mask;
  126. const struct xpcs_compat *compat;
  127. };
  128. static const struct xpcs_compat *xpcs_find_compat(const struct xpcs_id *id,
  129. phy_interface_t interface)
  130. {
  131. int i, j;
  132. for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
  133. const struct xpcs_compat *compat = &id->compat[i];
  134. for (j = 0; j < compat->num_interfaces; j++)
  135. if (compat->interface[j] == interface)
  136. return compat;
  137. }
  138. return NULL;
  139. }
  140. int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
  141. {
  142. const struct xpcs_compat *compat;
  143. compat = xpcs_find_compat(xpcs->id, interface);
  144. if (!compat)
  145. return -ENODEV;
  146. return compat->an_mode;
  147. }
  148. EXPORT_SYMBOL_GPL(xpcs_get_an_mode);
  149. static bool __xpcs_linkmode_supported(const struct xpcs_compat *compat,
  150. enum ethtool_link_mode_bit_indices linkmode)
  151. {
  152. int i;
  153. for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
  154. if (compat->supported[i] == linkmode)
  155. return true;
  156. return false;
  157. }
  158. #define xpcs_linkmode_supported(compat, mode) \
  159. __xpcs_linkmode_supported(compat, ETHTOOL_LINK_MODE_ ## mode ## _BIT)
  160. int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg)
  161. {
  162. struct mii_bus *bus = xpcs->mdiodev->bus;
  163. int addr = xpcs->mdiodev->addr;
  164. return mdiobus_c45_read(bus, addr, dev, reg);
  165. }
  166. int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
  167. {
  168. struct mii_bus *bus = xpcs->mdiodev->bus;
  169. int addr = xpcs->mdiodev->addr;
  170. return mdiobus_c45_write(bus, addr, dev, reg, val);
  171. }
  172. static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
  173. u16 mask, u16 set)
  174. {
  175. u32 reg_addr = mdiobus_c45_addr(dev, reg);
  176. return mdiodev_modify_changed(xpcs->mdiodev, reg_addr, mask, set);
  177. }
  178. static int xpcs_read_vendor(struct dw_xpcs *xpcs, int dev, u32 reg)
  179. {
  180. return xpcs_read(xpcs, dev, DW_VENDOR | reg);
  181. }
  182. static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg,
  183. u16 val)
  184. {
  185. return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
  186. }
  187. static int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg)
  188. {
  189. return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
  190. }
  191. static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
  192. {
  193. return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
  194. }
  195. static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
  196. {
  197. /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
  198. unsigned int retries = 12;
  199. int ret;
  200. do {
  201. msleep(50);
  202. ret = xpcs_read(xpcs, dev, MDIO_CTRL1);
  203. if (ret < 0)
  204. return ret;
  205. } while (ret & MDIO_CTRL1_RESET && --retries);
  206. return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0;
  207. }
  208. static int xpcs_soft_reset(struct dw_xpcs *xpcs,
  209. const struct xpcs_compat *compat)
  210. {
  211. int ret, dev;
  212. switch (compat->an_mode) {
  213. case DW_AN_C73:
  214. dev = MDIO_MMD_PCS;
  215. break;
  216. case DW_AN_C37_SGMII:
  217. case DW_2500BASEX:
  218. case DW_AN_C37_1000BASEX:
  219. dev = MDIO_MMD_VEND2;
  220. break;
  221. default:
  222. return -1;
  223. }
  224. ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET);
  225. if (ret < 0)
  226. return ret;
  227. return xpcs_poll_reset(xpcs, dev);
  228. }
  229. #define xpcs_warn(__xpcs, __state, __args...) \
  230. ({ \
  231. if ((__state)->link) \
  232. dev_warn(&(__xpcs)->mdiodev->dev, ##__args); \
  233. })
  234. static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
  235. struct phylink_link_state *state)
  236. {
  237. int ret;
  238. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
  239. if (ret < 0)
  240. return ret;
  241. if (ret & MDIO_STAT1_FAULT) {
  242. xpcs_warn(xpcs, state, "Link fault condition detected!\n");
  243. return -EFAULT;
  244. }
  245. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2);
  246. if (ret < 0)
  247. return ret;
  248. if (ret & MDIO_STAT2_RXFAULT)
  249. xpcs_warn(xpcs, state, "Receiver fault detected!\n");
  250. if (ret & MDIO_STAT2_TXFAULT)
  251. xpcs_warn(xpcs, state, "Transmitter fault detected!\n");
  252. ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS);
  253. if (ret < 0)
  254. return ret;
  255. if (ret & DW_RXFIFO_ERR) {
  256. xpcs_warn(xpcs, state, "FIFO fault condition detected!\n");
  257. return -EFAULT;
  258. }
  259. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
  260. if (ret < 0)
  261. return ret;
  262. if (!(ret & MDIO_PCS_10GBRT_STAT1_BLKLK))
  263. xpcs_warn(xpcs, state, "Link is not locked!\n");
  264. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2);
  265. if (ret < 0)
  266. return ret;
  267. if (ret & MDIO_PCS_10GBRT_STAT2_ERR) {
  268. xpcs_warn(xpcs, state, "Link has errors!\n");
  269. return -EFAULT;
  270. }
  271. return 0;
  272. }
  273. static int xpcs_read_link_c73(struct dw_xpcs *xpcs)
  274. {
  275. bool link = true;
  276. int ret;
  277. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
  278. if (ret < 0)
  279. return ret;
  280. if (!(ret & MDIO_STAT1_LSTATUS))
  281. link = false;
  282. return link;
  283. }
  284. static int xpcs_get_max_usxgmii_speed(const unsigned long *supported)
  285. {
  286. int max = SPEED_UNKNOWN;
  287. if (phylink_test(supported, 1000baseKX_Full))
  288. max = SPEED_1000;
  289. if (phylink_test(supported, 2500baseX_Full))
  290. max = SPEED_2500;
  291. if (phylink_test(supported, 10000baseKX4_Full))
  292. max = SPEED_10000;
  293. if (phylink_test(supported, 10000baseKR_Full))
  294. max = SPEED_10000;
  295. return max;
  296. }
  297. static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
  298. {
  299. int ret, speed_sel;
  300. switch (speed) {
  301. case SPEED_10:
  302. speed_sel = DW_USXGMII_10;
  303. break;
  304. case SPEED_100:
  305. speed_sel = DW_USXGMII_100;
  306. break;
  307. case SPEED_1000:
  308. speed_sel = DW_USXGMII_1000;
  309. break;
  310. case SPEED_2500:
  311. speed_sel = DW_USXGMII_2500;
  312. break;
  313. case SPEED_5000:
  314. speed_sel = DW_USXGMII_5000;
  315. break;
  316. case SPEED_10000:
  317. speed_sel = DW_USXGMII_10000;
  318. break;
  319. default:
  320. /* Nothing to do here */
  321. return;
  322. }
  323. ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
  324. if (ret < 0)
  325. goto out;
  326. ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN);
  327. if (ret < 0)
  328. goto out;
  329. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
  330. if (ret < 0)
  331. goto out;
  332. ret &= ~DW_USXGMII_SS_MASK;
  333. ret |= speed_sel | DW_USXGMII_FULL;
  334. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
  335. if (ret < 0)
  336. goto out;
  337. ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
  338. if (ret < 0)
  339. goto out;
  340. ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST);
  341. if (ret < 0)
  342. goto out;
  343. return;
  344. out:
  345. pr_err("%s: XPCS access returned %pe\n", __func__, ERR_PTR(ret));
  346. }
  347. static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
  348. const struct xpcs_compat *compat)
  349. {
  350. int ret, adv;
  351. /* By default, in USXGMII mode XPCS operates at 10G baud and
  352. * replicates data to achieve lower speeds. Hereby, in this
  353. * default configuration we need to advertise all supported
  354. * modes and not only the ones we want to use.
  355. */
  356. /* SR_AN_ADV3 */
  357. adv = 0;
  358. if (xpcs_linkmode_supported(compat, 2500baseX_Full))
  359. adv |= DW_C73_2500KX;
  360. /* TODO: 5000baseKR */
  361. ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv);
  362. if (ret < 0)
  363. return ret;
  364. /* SR_AN_ADV2 */
  365. adv = 0;
  366. if (xpcs_linkmode_supported(compat, 1000baseKX_Full))
  367. adv |= DW_C73_1000KX;
  368. if (xpcs_linkmode_supported(compat, 10000baseKX4_Full))
  369. adv |= DW_C73_10000KX4;
  370. if (xpcs_linkmode_supported(compat, 10000baseKR_Full))
  371. adv |= DW_C73_10000KR;
  372. ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv);
  373. if (ret < 0)
  374. return ret;
  375. /* SR_AN_ADV1 */
  376. adv = DW_C73_AN_ADV_SF;
  377. if (xpcs_linkmode_supported(compat, Pause))
  378. adv |= DW_C73_PAUSE;
  379. if (xpcs_linkmode_supported(compat, Asym_Pause))
  380. adv |= DW_C73_ASYM_PAUSE;
  381. return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv);
  382. }
  383. static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
  384. const struct xpcs_compat *compat)
  385. {
  386. int ret;
  387. ret = _xpcs_config_aneg_c73(xpcs, compat);
  388. if (ret < 0)
  389. return ret;
  390. ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1);
  391. if (ret < 0)
  392. return ret;
  393. ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
  394. return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret);
  395. }
  396. static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
  397. struct phylink_link_state *state,
  398. const struct xpcs_compat *compat)
  399. {
  400. int ret;
  401. ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
  402. if (ret < 0)
  403. return ret;
  404. if (ret & MDIO_AN_STAT1_COMPLETE) {
  405. ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
  406. if (ret < 0)
  407. return ret;
  408. /* Check if Aneg outcome is valid */
  409. if (!(ret & DW_C73_AN_ADV_SF)) {
  410. xpcs_config_aneg_c73(xpcs, compat);
  411. return 0;
  412. }
  413. return 1;
  414. }
  415. return 0;
  416. }
  417. static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
  418. struct phylink_link_state *state)
  419. {
  420. int ret;
  421. ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
  422. if (ret < 0)
  423. return ret;
  424. if (!(ret & MDIO_AN_STAT1_LPABLE)) {
  425. phylink_clear(state->lp_advertising, Autoneg);
  426. return 0;
  427. }
  428. phylink_set(state->lp_advertising, Autoneg);
  429. /* Clause 73 outcome */
  430. ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3);
  431. if (ret < 0)
  432. return ret;
  433. if (ret & DW_C73_2500KX)
  434. phylink_set(state->lp_advertising, 2500baseX_Full);
  435. ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2);
  436. if (ret < 0)
  437. return ret;
  438. if (ret & DW_C73_1000KX)
  439. phylink_set(state->lp_advertising, 1000baseKX_Full);
  440. if (ret & DW_C73_10000KX4)
  441. phylink_set(state->lp_advertising, 10000baseKX4_Full);
  442. if (ret & DW_C73_10000KR)
  443. phylink_set(state->lp_advertising, 10000baseKR_Full);
  444. ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
  445. if (ret < 0)
  446. return ret;
  447. if (ret & DW_C73_PAUSE)
  448. phylink_set(state->lp_advertising, Pause);
  449. if (ret & DW_C73_ASYM_PAUSE)
  450. phylink_set(state->lp_advertising, Asym_Pause);
  451. linkmode_and(state->lp_advertising, state->lp_advertising,
  452. state->advertising);
  453. return 0;
  454. }
  455. static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
  456. struct phylink_link_state *state)
  457. {
  458. int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising);
  459. state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
  460. state->speed = max_speed;
  461. state->duplex = DUPLEX_FULL;
  462. }
  463. static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
  464. struct phylink_link_state *state)
  465. {
  466. unsigned long *adv = state->advertising;
  467. int speed = SPEED_UNKNOWN;
  468. int bit;
  469. for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) {
  470. int new_speed = SPEED_UNKNOWN;
  471. switch (bit) {
  472. case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT:
  473. case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT:
  474. case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT:
  475. new_speed = SPEED_25000;
  476. break;
  477. case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT:
  478. case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT:
  479. case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT:
  480. case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT:
  481. new_speed = SPEED_40000;
  482. break;
  483. case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT:
  484. case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT:
  485. case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT:
  486. case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT:
  487. case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT:
  488. case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT:
  489. case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT:
  490. case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT:
  491. new_speed = SPEED_50000;
  492. break;
  493. case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT:
  494. case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT:
  495. case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT:
  496. case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT:
  497. case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT:
  498. case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT:
  499. case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT:
  500. case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT:
  501. case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT:
  502. new_speed = SPEED_100000;
  503. break;
  504. default:
  505. continue;
  506. }
  507. if (new_speed > speed)
  508. speed = new_speed;
  509. }
  510. return speed;
  511. }
  512. static void xpcs_resolve_pma(struct dw_xpcs *xpcs,
  513. struct phylink_link_state *state)
  514. {
  515. state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
  516. state->duplex = DUPLEX_FULL;
  517. switch (state->interface) {
  518. case PHY_INTERFACE_MODE_10GKR:
  519. state->speed = SPEED_10000;
  520. break;
  521. case PHY_INTERFACE_MODE_XLGMII:
  522. state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
  523. break;
  524. default:
  525. state->speed = SPEED_UNKNOWN;
  526. break;
  527. }
  528. }
  529. static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
  530. const struct phylink_link_state *state)
  531. {
  532. __ETHTOOL_DECLARE_LINK_MODE_MASK(xpcs_supported) = { 0, };
  533. const struct xpcs_compat *compat;
  534. struct dw_xpcs *xpcs;
  535. int i;
  536. xpcs = phylink_pcs_to_xpcs(pcs);
  537. compat = xpcs_find_compat(xpcs->id, state->interface);
  538. /* Populate the supported link modes for this PHY interface type.
  539. * FIXME: what about the port modes and autoneg bit? This masks
  540. * all those away.
  541. */
  542. if (compat)
  543. for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
  544. set_bit(compat->supported[i], xpcs_supported);
  545. linkmode_and(supported, supported, xpcs_supported);
  546. return 0;
  547. }
  548. void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
  549. {
  550. int i, j;
  551. for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
  552. const struct xpcs_compat *compat = &xpcs->id->compat[i];
  553. for (j = 0; j < compat->num_interfaces; j++)
  554. if (compat->interface[j] < PHY_INTERFACE_MODE_MAX)
  555. __set_bit(compat->interface[j], interfaces);
  556. }
  557. }
  558. EXPORT_SYMBOL_GPL(xpcs_get_interfaces);
  559. int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
  560. {
  561. int ret;
  562. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0);
  563. if (ret < 0)
  564. return ret;
  565. if (enable) {
  566. /* Enable EEE */
  567. ret = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
  568. DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
  569. DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
  570. mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT;
  571. } else {
  572. ret &= ~(DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
  573. DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
  574. DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
  575. DW_VR_MII_EEE_MULT_FACT_100NS);
  576. }
  577. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret);
  578. if (ret < 0)
  579. return ret;
  580. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1);
  581. if (ret < 0)
  582. return ret;
  583. if (enable)
  584. ret |= DW_VR_MII_EEE_TRN_LPI;
  585. else
  586. ret &= ~DW_VR_MII_EEE_TRN_LPI;
  587. return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret);
  588. }
  589. EXPORT_SYMBOL_GPL(xpcs_config_eee);
  590. static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
  591. {
  592. int ret, mdio_ctrl;
  593. /* For AN for C37 SGMII mode, the settings are :-
  594. * 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case
  595. it is already enabled)
  596. * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 10b (SGMII AN)
  597. * 3) VR_MII_AN_CTRL Bit(3) [TX_CONFIG] = 0b (MAC side SGMII)
  598. * DW xPCS used with DW EQoS MAC is always MAC side SGMII.
  599. * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic
  600. * speed/duplex mode change by HW after SGMII AN complete)
  601. * 5) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 1b (Enable SGMII AN)
  602. *
  603. * Note: Since it is MAC side SGMII, there is no need to set
  604. * SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config from
  605. * PHY about the link state change after C28 AN is completed
  606. * between PHY and Link Partner. There is also no need to
  607. * trigger AN restart for MAC-side SGMII.
  608. */
  609. mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
  610. if (mdio_ctrl < 0)
  611. return mdio_ctrl;
  612. if (mdio_ctrl & AN_CL37_EN) {
  613. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
  614. mdio_ctrl & ~AN_CL37_EN);
  615. if (ret < 0)
  616. return ret;
  617. }
  618. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
  619. if (ret < 0)
  620. return ret;
  621. ret &= ~(DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK);
  622. ret |= (DW_VR_MII_PCS_MODE_C37_SGMII <<
  623. DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT &
  624. DW_VR_MII_PCS_MODE_MASK);
  625. ret |= (DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII <<
  626. DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT &
  627. DW_VR_MII_TX_CONFIG_MASK);
  628. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
  629. if (ret < 0)
  630. return ret;
  631. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
  632. if (ret < 0)
  633. return ret;
  634. if (phylink_autoneg_inband(mode))
  635. ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
  636. else
  637. ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
  638. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
  639. if (ret < 0)
  640. return ret;
  641. if (phylink_autoneg_inband(mode))
  642. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
  643. mdio_ctrl | AN_CL37_EN);
  644. return ret;
  645. }
  646. static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
  647. const unsigned long *advertising)
  648. {
  649. phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
  650. int ret, mdio_ctrl, adv;
  651. bool changed = 0;
  652. /* According to Chap 7.12, to set 1000BASE-X C37 AN, AN must
  653. * be disabled first:-
  654. * 1) VR_MII_MMD_CTRL Bit(12)[AN_ENABLE] = 0b
  655. * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37)
  656. */
  657. mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
  658. if (mdio_ctrl < 0)
  659. return mdio_ctrl;
  660. if (mdio_ctrl & AN_CL37_EN) {
  661. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
  662. mdio_ctrl & ~AN_CL37_EN);
  663. if (ret < 0)
  664. return ret;
  665. }
  666. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
  667. if (ret < 0)
  668. return ret;
  669. ret &= ~DW_VR_MII_PCS_MODE_MASK;
  670. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
  671. if (ret < 0)
  672. return ret;
  673. /* Check for advertising changes and update the C45 MII ADV
  674. * register accordingly.
  675. */
  676. adv = phylink_mii_c22_pcs_encode_advertisement(interface,
  677. advertising);
  678. if (adv >= 0) {
  679. ret = xpcs_modify_changed(xpcs, MDIO_MMD_VEND2,
  680. MII_ADVERTISE, 0xffff, adv);
  681. if (ret < 0)
  682. return ret;
  683. changed = ret;
  684. }
  685. /* Clear CL37 AN complete status */
  686. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
  687. if (ret < 0)
  688. return ret;
  689. if (phylink_autoneg_inband(mode) &&
  690. linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
  691. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
  692. mdio_ctrl | AN_CL37_EN);
  693. if (ret < 0)
  694. return ret;
  695. }
  696. return changed;
  697. }
  698. static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
  699. {
  700. int ret;
  701. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
  702. if (ret < 0)
  703. return ret;
  704. ret |= DW_VR_MII_DIG_CTRL1_2G5_EN;
  705. ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
  706. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
  707. if (ret < 0)
  708. return ret;
  709. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
  710. if (ret < 0)
  711. return ret;
  712. ret &= ~AN_CL37_EN;
  713. ret |= SGMII_SPEED_SS6;
  714. ret &= ~SGMII_SPEED_SS13;
  715. return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, ret);
  716. }
  717. int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
  718. unsigned int mode, const unsigned long *advertising)
  719. {
  720. const struct xpcs_compat *compat;
  721. int ret;
  722. compat = xpcs_find_compat(xpcs->id, interface);
  723. if (!compat)
  724. return -ENODEV;
  725. switch (compat->an_mode) {
  726. case DW_AN_C73:
  727. if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
  728. ret = xpcs_config_aneg_c73(xpcs, compat);
  729. if (ret)
  730. return ret;
  731. }
  732. break;
  733. case DW_AN_C37_SGMII:
  734. ret = xpcs_config_aneg_c37_sgmii(xpcs, mode);
  735. if (ret)
  736. return ret;
  737. break;
  738. case DW_AN_C37_1000BASEX:
  739. ret = xpcs_config_aneg_c37_1000basex(xpcs, mode,
  740. advertising);
  741. if (ret)
  742. return ret;
  743. break;
  744. case DW_2500BASEX:
  745. ret = xpcs_config_2500basex(xpcs);
  746. if (ret)
  747. return ret;
  748. break;
  749. default:
  750. return -1;
  751. }
  752. if (compat->pma_config) {
  753. ret = compat->pma_config(xpcs);
  754. if (ret)
  755. return ret;
  756. }
  757. return 0;
  758. }
  759. EXPORT_SYMBOL_GPL(xpcs_do_config);
  760. static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode,
  761. phy_interface_t interface,
  762. const unsigned long *advertising,
  763. bool permit_pause_to_mac)
  764. {
  765. struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
  766. return xpcs_do_config(xpcs, interface, mode, advertising);
  767. }
  768. static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
  769. struct phylink_link_state *state,
  770. const struct xpcs_compat *compat)
  771. {
  772. int ret;
  773. /* Link needs to be read first ... */
  774. state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0;
  775. /* ... and then we check the faults. */
  776. ret = xpcs_read_fault_c73(xpcs, state);
  777. if (ret) {
  778. ret = xpcs_soft_reset(xpcs, compat);
  779. if (ret)
  780. return ret;
  781. state->link = 0;
  782. return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL);
  783. }
  784. if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) {
  785. state->an_complete = true;
  786. xpcs_read_lpa_c73(xpcs, state);
  787. xpcs_resolve_lpa_c73(xpcs, state);
  788. } else if (state->an_enabled) {
  789. state->link = 0;
  790. } else if (state->link) {
  791. xpcs_resolve_pma(xpcs, state);
  792. }
  793. return 0;
  794. }
  795. static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
  796. struct phylink_link_state *state)
  797. {
  798. int ret;
  799. /* Reset link_state */
  800. state->link = false;
  801. state->speed = SPEED_UNKNOWN;
  802. state->duplex = DUPLEX_UNKNOWN;
  803. state->pause = 0;
  804. /* For C37 SGMII mode, we check DW_VR_MII_AN_INTR_STS for link
  805. * status, speed and duplex.
  806. */
  807. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS);
  808. if (ret < 0)
  809. return ret;
  810. if (ret & DW_VR_MII_C37_ANSGM_SP_LNKSTS) {
  811. int speed_value;
  812. state->link = true;
  813. speed_value = (ret & DW_VR_MII_AN_STS_C37_ANSGM_SP) >>
  814. DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT;
  815. if (speed_value == DW_VR_MII_C37_ANSGM_SP_1000)
  816. state->speed = SPEED_1000;
  817. else if (speed_value == DW_VR_MII_C37_ANSGM_SP_100)
  818. state->speed = SPEED_100;
  819. else
  820. state->speed = SPEED_10;
  821. if (ret & DW_VR_MII_AN_STS_C37_ANSGM_FD)
  822. state->duplex = DUPLEX_FULL;
  823. else
  824. state->duplex = DUPLEX_HALF;
  825. }
  826. return 0;
  827. }
  828. static int xpcs_get_state_c37_1000basex(struct dw_xpcs *xpcs,
  829. struct phylink_link_state *state)
  830. {
  831. int lpa, bmsr;
  832. if (state->an_enabled) {
  833. /* Reset link state */
  834. state->link = false;
  835. lpa = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_LPA);
  836. if (lpa < 0 || lpa & LPA_RFAULT)
  837. return lpa;
  838. bmsr = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
  839. if (bmsr < 0)
  840. return bmsr;
  841. phylink_mii_c22_pcs_decode_state(state, bmsr, lpa);
  842. }
  843. return 0;
  844. }
  845. static void xpcs_get_state(struct phylink_pcs *pcs,
  846. struct phylink_link_state *state)
  847. {
  848. struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
  849. const struct xpcs_compat *compat;
  850. int ret;
  851. compat = xpcs_find_compat(xpcs->id, state->interface);
  852. if (!compat)
  853. return;
  854. switch (compat->an_mode) {
  855. case DW_AN_C73:
  856. ret = xpcs_get_state_c73(xpcs, state, compat);
  857. if (ret) {
  858. pr_err("xpcs_get_state_c73 returned %pe\n",
  859. ERR_PTR(ret));
  860. return;
  861. }
  862. break;
  863. case DW_AN_C37_SGMII:
  864. ret = xpcs_get_state_c37_sgmii(xpcs, state);
  865. if (ret) {
  866. pr_err("xpcs_get_state_c37_sgmii returned %pe\n",
  867. ERR_PTR(ret));
  868. }
  869. break;
  870. case DW_AN_C37_1000BASEX:
  871. ret = xpcs_get_state_c37_1000basex(xpcs, state);
  872. if (ret) {
  873. pr_err("xpcs_get_state_c37_1000basex returned %pe\n",
  874. ERR_PTR(ret));
  875. }
  876. break;
  877. default:
  878. return;
  879. }
  880. }
  881. static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
  882. int speed, int duplex)
  883. {
  884. int val, ret;
  885. if (phylink_autoneg_inband(mode))
  886. return;
  887. val = mii_bmcr_encode_fixed(speed, duplex);
  888. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
  889. if (ret)
  890. pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
  891. }
  892. static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
  893. int speed, int duplex)
  894. {
  895. int val, ret;
  896. if (phylink_autoneg_inband(mode))
  897. return;
  898. switch (speed) {
  899. case SPEED_1000:
  900. val = BMCR_SPEED1000;
  901. break;
  902. case SPEED_100:
  903. case SPEED_10:
  904. default:
  905. pr_err("%s: speed = %d\n", __func__, speed);
  906. return;
  907. }
  908. if (duplex == DUPLEX_FULL)
  909. val |= BMCR_FULLDPLX;
  910. else
  911. pr_err("%s: half duplex not supported\n", __func__);
  912. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
  913. if (ret)
  914. pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
  915. }
  916. void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
  917. phy_interface_t interface, int speed, int duplex)
  918. {
  919. struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
  920. if (interface == PHY_INTERFACE_MODE_USXGMII)
  921. return xpcs_config_usxgmii(xpcs, speed);
  922. if (interface == PHY_INTERFACE_MODE_SGMII)
  923. return xpcs_link_up_sgmii(xpcs, mode, speed, duplex);
  924. if (interface == PHY_INTERFACE_MODE_1000BASEX)
  925. return xpcs_link_up_1000basex(xpcs, mode, speed, duplex);
  926. }
  927. EXPORT_SYMBOL_GPL(xpcs_link_up);
  928. static void xpcs_an_restart(struct phylink_pcs *pcs)
  929. {
  930. struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
  931. int ret;
  932. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
  933. if (ret >= 0) {
  934. ret |= BMCR_ANRESTART;
  935. xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
  936. }
  937. }
  938. static u32 xpcs_get_id(struct dw_xpcs *xpcs)
  939. {
  940. int ret;
  941. u32 id;
  942. /* First, search C73 PCS using PCS MMD */
  943. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1);
  944. if (ret < 0)
  945. return 0xffffffff;
  946. id = ret << 16;
  947. ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2);
  948. if (ret < 0)
  949. return 0xffffffff;
  950. /* If Device IDs are not all zeros or all ones,
  951. * we found C73 AN-type device
  952. */
  953. if ((id | ret) && (id | ret) != 0xffffffff)
  954. return id | ret;
  955. /* Next, search C37 PCS using Vendor-Specific MII MMD */
  956. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID1);
  957. if (ret < 0)
  958. return 0xffffffff;
  959. id = ret << 16;
  960. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID2);
  961. if (ret < 0)
  962. return 0xffffffff;
  963. /* If Device IDs are not all zeros, we found C37 AN-type device */
  964. if (id | ret)
  965. return id | ret;
  966. return 0xffffffff;
  967. }
  968. static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
  969. [DW_XPCS_USXGMII] = {
  970. .supported = xpcs_usxgmii_features,
  971. .interface = xpcs_usxgmii_interfaces,
  972. .num_interfaces = ARRAY_SIZE(xpcs_usxgmii_interfaces),
  973. .an_mode = DW_AN_C73,
  974. },
  975. [DW_XPCS_10GKR] = {
  976. .supported = xpcs_10gkr_features,
  977. .interface = xpcs_10gkr_interfaces,
  978. .num_interfaces = ARRAY_SIZE(xpcs_10gkr_interfaces),
  979. .an_mode = DW_AN_C73,
  980. },
  981. [DW_XPCS_XLGMII] = {
  982. .supported = xpcs_xlgmii_features,
  983. .interface = xpcs_xlgmii_interfaces,
  984. .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
  985. .an_mode = DW_AN_C73,
  986. },
  987. [DW_XPCS_SGMII] = {
  988. .supported = xpcs_sgmii_features,
  989. .interface = xpcs_sgmii_interfaces,
  990. .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
  991. .an_mode = DW_AN_C37_SGMII,
  992. },
  993. [DW_XPCS_1000BASEX] = {
  994. .supported = xpcs_1000basex_features,
  995. .interface = xpcs_1000basex_interfaces,
  996. .num_interfaces = ARRAY_SIZE(xpcs_1000basex_interfaces),
  997. .an_mode = DW_AN_C37_1000BASEX,
  998. },
  999. [DW_XPCS_2500BASEX] = {
  1000. .supported = xpcs_2500basex_features,
  1001. .interface = xpcs_2500basex_interfaces,
  1002. .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features),
  1003. .an_mode = DW_2500BASEX,
  1004. },
  1005. };
  1006. static const struct xpcs_compat nxp_sja1105_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
  1007. [DW_XPCS_SGMII] = {
  1008. .supported = xpcs_sgmii_features,
  1009. .interface = xpcs_sgmii_interfaces,
  1010. .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
  1011. .an_mode = DW_AN_C37_SGMII,
  1012. .pma_config = nxp_sja1105_sgmii_pma_config,
  1013. },
  1014. };
  1015. static const struct xpcs_compat nxp_sja1110_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
  1016. [DW_XPCS_SGMII] = {
  1017. .supported = xpcs_sgmii_features,
  1018. .interface = xpcs_sgmii_interfaces,
  1019. .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
  1020. .an_mode = DW_AN_C37_SGMII,
  1021. .pma_config = nxp_sja1110_sgmii_pma_config,
  1022. },
  1023. [DW_XPCS_2500BASEX] = {
  1024. .supported = xpcs_2500basex_features,
  1025. .interface = xpcs_2500basex_interfaces,
  1026. .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
  1027. .an_mode = DW_2500BASEX,
  1028. .pma_config = nxp_sja1110_2500basex_pma_config,
  1029. },
  1030. };
  1031. static const struct xpcs_id xpcs_id_list[] = {
  1032. {
  1033. .id = SYNOPSYS_XPCS_ID,
  1034. .mask = SYNOPSYS_XPCS_MASK,
  1035. .compat = synopsys_xpcs_compat,
  1036. }, {
  1037. .id = NXP_SJA1105_XPCS_ID,
  1038. .mask = SYNOPSYS_XPCS_MASK,
  1039. .compat = nxp_sja1105_xpcs_compat,
  1040. }, {
  1041. .id = NXP_SJA1110_XPCS_ID,
  1042. .mask = SYNOPSYS_XPCS_MASK,
  1043. .compat = nxp_sja1110_xpcs_compat,
  1044. },
  1045. };
  1046. static const struct phylink_pcs_ops xpcs_phylink_ops = {
  1047. .pcs_validate = xpcs_validate,
  1048. .pcs_config = xpcs_config,
  1049. .pcs_get_state = xpcs_get_state,
  1050. .pcs_an_restart = xpcs_an_restart,
  1051. .pcs_link_up = xpcs_link_up,
  1052. };
  1053. struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
  1054. phy_interface_t interface)
  1055. {
  1056. struct dw_xpcs *xpcs;
  1057. u32 xpcs_id;
  1058. int i, ret;
  1059. xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
  1060. if (!xpcs)
  1061. return ERR_PTR(-ENOMEM);
  1062. xpcs->mdiodev = mdiodev;
  1063. xpcs_id = xpcs_get_id(xpcs);
  1064. for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
  1065. const struct xpcs_id *entry = &xpcs_id_list[i];
  1066. const struct xpcs_compat *compat;
  1067. if ((xpcs_id & entry->mask) != entry->id)
  1068. continue;
  1069. xpcs->id = entry;
  1070. compat = xpcs_find_compat(entry, interface);
  1071. if (!compat) {
  1072. ret = -ENODEV;
  1073. goto out;
  1074. }
  1075. xpcs->pcs.ops = &xpcs_phylink_ops;
  1076. xpcs->pcs.poll = true;
  1077. ret = xpcs_soft_reset(xpcs, compat);
  1078. if (ret)
  1079. goto out;
  1080. return xpcs;
  1081. }
  1082. ret = -ENODEV;
  1083. out:
  1084. kfree(xpcs);
  1085. return ERR_PTR(ret);
  1086. }
  1087. EXPORT_SYMBOL_GPL(xpcs_create);
  1088. void xpcs_destroy(struct dw_xpcs *xpcs)
  1089. {
  1090. kfree(xpcs);
  1091. }
  1092. EXPORT_SYMBOL_GPL(xpcs_destroy);
  1093. MODULE_LICENSE("GPL v2");