phy-fsl-lynx-28g.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Copyright (c) 2021-2022 NXP. */
  3. #include <linux/module.h>
  4. #include <linux/phy.h>
  5. #include <linux/phy/phy.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/workqueue.h>
  8. #define LYNX_28G_NUM_LANE 8
  9. #define LYNX_28G_NUM_PLL 2
  10. /* General registers per SerDes block */
  11. #define LYNX_28G_PCC8 0x10a0
  12. #define LYNX_28G_PCC8_SGMII 0x1
  13. #define LYNX_28G_PCC8_SGMII_DIS 0x0
  14. #define LYNX_28G_PCCC 0x10b0
  15. #define LYNX_28G_PCCC_10GBASER 0x9
  16. #define LYNX_28G_PCCC_USXGMII 0x1
  17. #define LYNX_28G_PCCC_SXGMII_DIS 0x0
  18. #define LYNX_28G_LNa_PCC_OFFSET(lane) (4 * (LYNX_28G_NUM_LANE - (lane->id) - 1))
  19. /* Per PLL registers */
  20. #define LYNX_28G_PLLnRSTCTL(pll) (0x400 + (pll) * 0x100 + 0x0)
  21. #define LYNX_28G_PLLnRSTCTL_DIS(rstctl) (((rstctl) & BIT(24)) >> 24)
  22. #define LYNX_28G_PLLnRSTCTL_LOCK(rstctl) (((rstctl) & BIT(23)) >> 23)
  23. #define LYNX_28G_PLLnCR0(pll) (0x400 + (pll) * 0x100 + 0x4)
  24. #define LYNX_28G_PLLnCR0_REFCLK_SEL(cr0) (((cr0) & GENMASK(20, 16)))
  25. #define LYNX_28G_PLLnCR0_REFCLK_SEL_100MHZ 0x0
  26. #define LYNX_28G_PLLnCR0_REFCLK_SEL_125MHZ 0x10000
  27. #define LYNX_28G_PLLnCR0_REFCLK_SEL_156MHZ 0x20000
  28. #define LYNX_28G_PLLnCR0_REFCLK_SEL_150MHZ 0x30000
  29. #define LYNX_28G_PLLnCR0_REFCLK_SEL_161MHZ 0x40000
  30. #define LYNX_28G_PLLnCR1(pll) (0x400 + (pll) * 0x100 + 0x8)
  31. #define LYNX_28G_PLLnCR1_FRATE_SEL(cr1) (((cr1) & GENMASK(28, 24)))
  32. #define LYNX_28G_PLLnCR1_FRATE_5G_10GVCO 0x0
  33. #define LYNX_28G_PLLnCR1_FRATE_5G_25GVCO 0x10000000
  34. #define LYNX_28G_PLLnCR1_FRATE_10G_20GVCO 0x6000000
  35. /* Per SerDes lane registers */
  36. /* Lane a General Control Register */
  37. #define LYNX_28G_LNaGCR0(lane) (0x800 + (lane) * 0x100 + 0x0)
  38. #define LYNX_28G_LNaGCR0_PROTO_SEL_MSK GENMASK(7, 3)
  39. #define LYNX_28G_LNaGCR0_PROTO_SEL_SGMII 0x8
  40. #define LYNX_28G_LNaGCR0_PROTO_SEL_XFI 0x50
  41. #define LYNX_28G_LNaGCR0_IF_WIDTH_MSK GENMASK(2, 0)
  42. #define LYNX_28G_LNaGCR0_IF_WIDTH_10_BIT 0x0
  43. #define LYNX_28G_LNaGCR0_IF_WIDTH_20_BIT 0x2
  44. /* Lane a Tx Reset Control Register */
  45. #define LYNX_28G_LNaTRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x20)
  46. #define LYNX_28G_LNaTRSTCTL_HLT_REQ BIT(27)
  47. #define LYNX_28G_LNaTRSTCTL_RST_DONE BIT(30)
  48. #define LYNX_28G_LNaTRSTCTL_RST_REQ BIT(31)
  49. /* Lane a Tx General Control Register */
  50. #define LYNX_28G_LNaTGCR0(lane) (0x800 + (lane) * 0x100 + 0x24)
  51. #define LYNX_28G_LNaTGCR0_USE_PLLF 0x0
  52. #define LYNX_28G_LNaTGCR0_USE_PLLS BIT(28)
  53. #define LYNX_28G_LNaTGCR0_USE_PLL_MSK BIT(28)
  54. #define LYNX_28G_LNaTGCR0_N_RATE_FULL 0x0
  55. #define LYNX_28G_LNaTGCR0_N_RATE_HALF 0x1000000
  56. #define LYNX_28G_LNaTGCR0_N_RATE_QUARTER 0x2000000
  57. #define LYNX_28G_LNaTGCR0_N_RATE_MSK GENMASK(26, 24)
  58. #define LYNX_28G_LNaTECR0(lane) (0x800 + (lane) * 0x100 + 0x30)
  59. /* Lane a Rx Reset Control Register */
  60. #define LYNX_28G_LNaRRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x40)
  61. #define LYNX_28G_LNaRRSTCTL_HLT_REQ BIT(27)
  62. #define LYNX_28G_LNaRRSTCTL_RST_DONE BIT(30)
  63. #define LYNX_28G_LNaRRSTCTL_RST_REQ BIT(31)
  64. #define LYNX_28G_LNaRRSTCTL_CDR_LOCK BIT(12)
  65. /* Lane a Rx General Control Register */
  66. #define LYNX_28G_LNaRGCR0(lane) (0x800 + (lane) * 0x100 + 0x44)
  67. #define LYNX_28G_LNaRGCR0_USE_PLLF 0x0
  68. #define LYNX_28G_LNaRGCR0_USE_PLLS BIT(28)
  69. #define LYNX_28G_LNaRGCR0_USE_PLL_MSK BIT(28)
  70. #define LYNX_28G_LNaRGCR0_N_RATE_MSK GENMASK(26, 24)
  71. #define LYNX_28G_LNaRGCR0_N_RATE_FULL 0x0
  72. #define LYNX_28G_LNaRGCR0_N_RATE_HALF 0x1000000
  73. #define LYNX_28G_LNaRGCR0_N_RATE_QUARTER 0x2000000
  74. #define LYNX_28G_LNaRGCR0_N_RATE_MSK GENMASK(26, 24)
  75. #define LYNX_28G_LNaRGCR1(lane) (0x800 + (lane) * 0x100 + 0x48)
  76. #define LYNX_28G_LNaRECR0(lane) (0x800 + (lane) * 0x100 + 0x50)
  77. #define LYNX_28G_LNaRECR1(lane) (0x800 + (lane) * 0x100 + 0x54)
  78. #define LYNX_28G_LNaRECR2(lane) (0x800 + (lane) * 0x100 + 0x58)
  79. #define LYNX_28G_LNaRSCCR0(lane) (0x800 + (lane) * 0x100 + 0x74)
  80. #define LYNX_28G_LNaPSS(lane) (0x1000 + (lane) * 0x4)
  81. #define LYNX_28G_LNaPSS_TYPE(pss) (((pss) & GENMASK(30, 24)) >> 24)
  82. #define LYNX_28G_LNaPSS_TYPE_SGMII 0x4
  83. #define LYNX_28G_LNaPSS_TYPE_XFI 0x28
  84. #define LYNX_28G_SGMIIaCR1(lane) (0x1804 + (lane) * 0x10)
  85. #define LYNX_28G_SGMIIaCR1_SGPCS_EN BIT(11)
  86. #define LYNX_28G_SGMIIaCR1_SGPCS_DIS 0x0
  87. #define LYNX_28G_SGMIIaCR1_SGPCS_MSK BIT(11)
  88. struct lynx_28g_priv;
  89. struct lynx_28g_pll {
  90. struct lynx_28g_priv *priv;
  91. u32 rstctl, cr0, cr1;
  92. int id;
  93. DECLARE_PHY_INTERFACE_MASK(supported);
  94. };
  95. struct lynx_28g_lane {
  96. struct lynx_28g_priv *priv;
  97. struct phy *phy;
  98. bool powered_up;
  99. bool init;
  100. unsigned int id;
  101. phy_interface_t interface;
  102. };
  103. struct lynx_28g_priv {
  104. void __iomem *base;
  105. struct device *dev;
  106. /* Serialize concurrent access to registers shared between lanes,
  107. * like PCCn
  108. */
  109. spinlock_t pcc_lock;
  110. struct lynx_28g_pll pll[LYNX_28G_NUM_PLL];
  111. struct lynx_28g_lane lane[LYNX_28G_NUM_LANE];
  112. struct delayed_work cdr_check;
  113. };
  114. static void lynx_28g_rmw(struct lynx_28g_priv *priv, unsigned long off,
  115. u32 val, u32 mask)
  116. {
  117. void __iomem *reg = priv->base + off;
  118. u32 orig, tmp;
  119. orig = ioread32(reg);
  120. tmp = orig & ~mask;
  121. tmp |= val;
  122. iowrite32(tmp, reg);
  123. }
  124. #define lynx_28g_lane_rmw(lane, reg, val, mask) \
  125. lynx_28g_rmw((lane)->priv, LYNX_28G_##reg(lane->id), \
  126. LYNX_28G_##reg##_##val, LYNX_28G_##reg##_##mask)
  127. #define lynx_28g_lane_read(lane, reg) \
  128. ioread32((lane)->priv->base + LYNX_28G_##reg((lane)->id))
  129. #define lynx_28g_pll_read(pll, reg) \
  130. ioread32((pll)->priv->base + LYNX_28G_##reg((pll)->id))
  131. static bool lynx_28g_supports_interface(struct lynx_28g_priv *priv, int intf)
  132. {
  133. int i;
  134. for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
  135. if (LYNX_28G_PLLnRSTCTL_DIS(priv->pll[i].rstctl))
  136. continue;
  137. if (test_bit(intf, priv->pll[i].supported))
  138. return true;
  139. }
  140. return false;
  141. }
  142. static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv,
  143. phy_interface_t intf)
  144. {
  145. struct lynx_28g_pll *pll;
  146. int i;
  147. for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
  148. pll = &priv->pll[i];
  149. if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl))
  150. continue;
  151. if (test_bit(intf, pll->supported))
  152. return pll;
  153. }
  154. return NULL;
  155. }
  156. static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane,
  157. struct lynx_28g_pll *pll,
  158. phy_interface_t intf)
  159. {
  160. switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) {
  161. case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO:
  162. case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO:
  163. switch (intf) {
  164. case PHY_INTERFACE_MODE_SGMII:
  165. case PHY_INTERFACE_MODE_1000BASEX:
  166. lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_QUARTER, N_RATE_MSK);
  167. lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_QUARTER, N_RATE_MSK);
  168. break;
  169. default:
  170. break;
  171. }
  172. break;
  173. case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO:
  174. switch (intf) {
  175. case PHY_INTERFACE_MODE_10GBASER:
  176. case PHY_INTERFACE_MODE_USXGMII:
  177. lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_FULL, N_RATE_MSK);
  178. lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_FULL, N_RATE_MSK);
  179. break;
  180. default:
  181. break;
  182. }
  183. break;
  184. default:
  185. break;
  186. }
  187. }
  188. static void lynx_28g_lane_set_pll(struct lynx_28g_lane *lane,
  189. struct lynx_28g_pll *pll)
  190. {
  191. if (pll->id == 0) {
  192. lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLF, USE_PLL_MSK);
  193. lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLF, USE_PLL_MSK);
  194. } else {
  195. lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLS, USE_PLL_MSK);
  196. lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLS, USE_PLL_MSK);
  197. }
  198. }
  199. static void lynx_28g_cleanup_lane(struct lynx_28g_lane *lane)
  200. {
  201. u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
  202. struct lynx_28g_priv *priv = lane->priv;
  203. /* Cleanup the protocol configuration registers of the current protocol */
  204. switch (lane->interface) {
  205. case PHY_INTERFACE_MODE_10GBASER:
  206. lynx_28g_rmw(priv, LYNX_28G_PCCC,
  207. LYNX_28G_PCCC_SXGMII_DIS << lane_offset,
  208. GENMASK(3, 0) << lane_offset);
  209. break;
  210. case PHY_INTERFACE_MODE_SGMII:
  211. case PHY_INTERFACE_MODE_1000BASEX:
  212. lynx_28g_rmw(priv, LYNX_28G_PCC8,
  213. LYNX_28G_PCC8_SGMII_DIS << lane_offset,
  214. GENMASK(3, 0) << lane_offset);
  215. break;
  216. default:
  217. break;
  218. }
  219. }
  220. static void lynx_28g_lane_set_sgmii(struct lynx_28g_lane *lane)
  221. {
  222. u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
  223. struct lynx_28g_priv *priv = lane->priv;
  224. struct lynx_28g_pll *pll;
  225. lynx_28g_cleanup_lane(lane);
  226. /* Setup the lane to run in SGMII */
  227. lynx_28g_rmw(priv, LYNX_28G_PCC8,
  228. LYNX_28G_PCC8_SGMII << lane_offset,
  229. GENMASK(3, 0) << lane_offset);
  230. /* Setup the protocol select and SerDes parallel interface width */
  231. lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_SGMII, PROTO_SEL_MSK);
  232. lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_10_BIT, IF_WIDTH_MSK);
  233. /* Switch to the PLL that works with this interface type */
  234. pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_SGMII);
  235. lynx_28g_lane_set_pll(lane, pll);
  236. /* Choose the portion of clock net to be used on this lane */
  237. lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_SGMII);
  238. /* Enable the SGMII PCS */
  239. lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_EN, SGPCS_MSK);
  240. /* Configure the appropriate equalization parameters for the protocol */
  241. iowrite32(0x00808006, priv->base + LYNX_28G_LNaTECR0(lane->id));
  242. iowrite32(0x04310000, priv->base + LYNX_28G_LNaRGCR1(lane->id));
  243. iowrite32(0x9f800000, priv->base + LYNX_28G_LNaRECR0(lane->id));
  244. iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id));
  245. iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR2(lane->id));
  246. iowrite32(0x00000000, priv->base + LYNX_28G_LNaRSCCR0(lane->id));
  247. }
  248. static void lynx_28g_lane_set_10gbaser(struct lynx_28g_lane *lane)
  249. {
  250. u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
  251. struct lynx_28g_priv *priv = lane->priv;
  252. struct lynx_28g_pll *pll;
  253. lynx_28g_cleanup_lane(lane);
  254. /* Enable the SXGMII lane */
  255. lynx_28g_rmw(priv, LYNX_28G_PCCC,
  256. LYNX_28G_PCCC_10GBASER << lane_offset,
  257. GENMASK(3, 0) << lane_offset);
  258. /* Setup the protocol select and SerDes parallel interface width */
  259. lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_XFI, PROTO_SEL_MSK);
  260. lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_20_BIT, IF_WIDTH_MSK);
  261. /* Switch to the PLL that works with this interface type */
  262. pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_10GBASER);
  263. lynx_28g_lane_set_pll(lane, pll);
  264. /* Choose the portion of clock net to be used on this lane */
  265. lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_10GBASER);
  266. /* Disable the SGMII PCS */
  267. lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_DIS, SGPCS_MSK);
  268. /* Configure the appropriate equalization parameters for the protocol */
  269. iowrite32(0x10808307, priv->base + LYNX_28G_LNaTECR0(lane->id));
  270. iowrite32(0x10000000, priv->base + LYNX_28G_LNaRGCR1(lane->id));
  271. iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR0(lane->id));
  272. iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id));
  273. iowrite32(0x81000020, priv->base + LYNX_28G_LNaRECR2(lane->id));
  274. iowrite32(0x00002000, priv->base + LYNX_28G_LNaRSCCR0(lane->id));
  275. }
  276. static int lynx_28g_power_off(struct phy *phy)
  277. {
  278. struct lynx_28g_lane *lane = phy_get_drvdata(phy);
  279. u32 trstctl, rrstctl;
  280. if (!lane->powered_up)
  281. return 0;
  282. /* Issue a halt request */
  283. lynx_28g_lane_rmw(lane, LNaTRSTCTL, HLT_REQ, HLT_REQ);
  284. lynx_28g_lane_rmw(lane, LNaRRSTCTL, HLT_REQ, HLT_REQ);
  285. /* Wait until the halting process is complete */
  286. do {
  287. trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
  288. rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
  289. } while ((trstctl & LYNX_28G_LNaTRSTCTL_HLT_REQ) ||
  290. (rrstctl & LYNX_28G_LNaRRSTCTL_HLT_REQ));
  291. lane->powered_up = false;
  292. return 0;
  293. }
  294. static int lynx_28g_power_on(struct phy *phy)
  295. {
  296. struct lynx_28g_lane *lane = phy_get_drvdata(phy);
  297. u32 trstctl, rrstctl;
  298. if (lane->powered_up)
  299. return 0;
  300. /* Issue a reset request on the lane */
  301. lynx_28g_lane_rmw(lane, LNaTRSTCTL, RST_REQ, RST_REQ);
  302. lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ);
  303. /* Wait until the reset sequence is completed */
  304. do {
  305. trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
  306. rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
  307. } while (!(trstctl & LYNX_28G_LNaTRSTCTL_RST_DONE) ||
  308. !(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
  309. lane->powered_up = true;
  310. return 0;
  311. }
  312. static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
  313. {
  314. struct lynx_28g_lane *lane = phy_get_drvdata(phy);
  315. struct lynx_28g_priv *priv = lane->priv;
  316. int powered_up = lane->powered_up;
  317. int err = 0;
  318. if (mode != PHY_MODE_ETHERNET)
  319. return -EOPNOTSUPP;
  320. if (lane->interface == PHY_INTERFACE_MODE_NA)
  321. return -EOPNOTSUPP;
  322. if (!lynx_28g_supports_interface(priv, submode))
  323. return -EOPNOTSUPP;
  324. /* If the lane is powered up, put the lane into the halt state while
  325. * the reconfiguration is being done.
  326. */
  327. if (powered_up)
  328. lynx_28g_power_off(phy);
  329. spin_lock(&priv->pcc_lock);
  330. switch (submode) {
  331. case PHY_INTERFACE_MODE_SGMII:
  332. case PHY_INTERFACE_MODE_1000BASEX:
  333. lynx_28g_lane_set_sgmii(lane);
  334. break;
  335. case PHY_INTERFACE_MODE_10GBASER:
  336. lynx_28g_lane_set_10gbaser(lane);
  337. break;
  338. default:
  339. err = -EOPNOTSUPP;
  340. goto out;
  341. }
  342. lane->interface = submode;
  343. out:
  344. spin_unlock(&priv->pcc_lock);
  345. /* Power up the lane if necessary */
  346. if (powered_up)
  347. lynx_28g_power_on(phy);
  348. return err;
  349. }
  350. static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode,
  351. union phy_configure_opts *opts __always_unused)
  352. {
  353. struct lynx_28g_lane *lane = phy_get_drvdata(phy);
  354. struct lynx_28g_priv *priv = lane->priv;
  355. if (mode != PHY_MODE_ETHERNET)
  356. return -EOPNOTSUPP;
  357. if (!lynx_28g_supports_interface(priv, submode))
  358. return -EOPNOTSUPP;
  359. return 0;
  360. }
  361. static int lynx_28g_init(struct phy *phy)
  362. {
  363. struct lynx_28g_lane *lane = phy_get_drvdata(phy);
  364. /* Mark the fact that the lane was init */
  365. lane->init = true;
  366. /* SerDes lanes are powered on at boot time. Any lane that is managed
  367. * by this driver will get powered down at init time aka at dpaa2-eth
  368. * probe time.
  369. */
  370. lane->powered_up = true;
  371. lynx_28g_power_off(phy);
  372. return 0;
  373. }
  374. static const struct phy_ops lynx_28g_ops = {
  375. .init = lynx_28g_init,
  376. .power_on = lynx_28g_power_on,
  377. .power_off = lynx_28g_power_off,
  378. .set_mode = lynx_28g_set_mode,
  379. .validate = lynx_28g_validate,
  380. .owner = THIS_MODULE,
  381. };
  382. static void lynx_28g_pll_read_configuration(struct lynx_28g_priv *priv)
  383. {
  384. struct lynx_28g_pll *pll;
  385. int i;
  386. for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
  387. pll = &priv->pll[i];
  388. pll->priv = priv;
  389. pll->id = i;
  390. pll->rstctl = lynx_28g_pll_read(pll, PLLnRSTCTL);
  391. pll->cr0 = lynx_28g_pll_read(pll, PLLnCR0);
  392. pll->cr1 = lynx_28g_pll_read(pll, PLLnCR1);
  393. if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl))
  394. continue;
  395. switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) {
  396. case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO:
  397. case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO:
  398. /* 5GHz clock net */
  399. __set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported);
  400. __set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported);
  401. break;
  402. case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO:
  403. /* 10.3125GHz clock net */
  404. __set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported);
  405. break;
  406. default:
  407. /* 6GHz, 12.890625GHz, 8GHz */
  408. break;
  409. }
  410. }
  411. }
  412. #define work_to_lynx(w) container_of((w), struct lynx_28g_priv, cdr_check.work)
  413. static void lynx_28g_cdr_lock_check(struct work_struct *work)
  414. {
  415. struct lynx_28g_priv *priv = work_to_lynx(work);
  416. struct lynx_28g_lane *lane;
  417. u32 rrstctl;
  418. int i;
  419. for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
  420. lane = &priv->lane[i];
  421. mutex_lock(&lane->phy->mutex);
  422. if (!lane->init || !lane->powered_up) {
  423. mutex_unlock(&lane->phy->mutex);
  424. continue;
  425. }
  426. rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
  427. if (!(rrstctl & LYNX_28G_LNaRRSTCTL_CDR_LOCK)) {
  428. lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ);
  429. do {
  430. rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
  431. } while (!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
  432. }
  433. mutex_unlock(&lane->phy->mutex);
  434. }
  435. queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
  436. msecs_to_jiffies(1000));
  437. }
  438. static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane)
  439. {
  440. u32 pss, protocol;
  441. pss = lynx_28g_lane_read(lane, LNaPSS);
  442. protocol = LYNX_28G_LNaPSS_TYPE(pss);
  443. switch (protocol) {
  444. case LYNX_28G_LNaPSS_TYPE_SGMII:
  445. lane->interface = PHY_INTERFACE_MODE_SGMII;
  446. break;
  447. case LYNX_28G_LNaPSS_TYPE_XFI:
  448. lane->interface = PHY_INTERFACE_MODE_10GBASER;
  449. break;
  450. default:
  451. lane->interface = PHY_INTERFACE_MODE_NA;
  452. }
  453. }
  454. static struct phy *lynx_28g_xlate(struct device *dev,
  455. struct of_phandle_args *args)
  456. {
  457. struct lynx_28g_priv *priv = dev_get_drvdata(dev);
  458. int idx = args->args[0];
  459. if (WARN_ON(idx >= LYNX_28G_NUM_LANE))
  460. return ERR_PTR(-EINVAL);
  461. return priv->lane[idx].phy;
  462. }
  463. static int lynx_28g_probe(struct platform_device *pdev)
  464. {
  465. struct device *dev = &pdev->dev;
  466. struct phy_provider *provider;
  467. struct lynx_28g_priv *priv;
  468. int i;
  469. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  470. if (!priv)
  471. return -ENOMEM;
  472. priv->dev = &pdev->dev;
  473. priv->base = devm_platform_ioremap_resource(pdev, 0);
  474. if (IS_ERR(priv->base))
  475. return PTR_ERR(priv->base);
  476. lynx_28g_pll_read_configuration(priv);
  477. for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
  478. struct lynx_28g_lane *lane = &priv->lane[i];
  479. struct phy *phy;
  480. memset(lane, 0, sizeof(*lane));
  481. phy = devm_phy_create(&pdev->dev, NULL, &lynx_28g_ops);
  482. if (IS_ERR(phy))
  483. return PTR_ERR(phy);
  484. lane->priv = priv;
  485. lane->phy = phy;
  486. lane->id = i;
  487. phy_set_drvdata(phy, lane);
  488. lynx_28g_lane_read_configuration(lane);
  489. }
  490. dev_set_drvdata(dev, priv);
  491. spin_lock_init(&priv->pcc_lock);
  492. INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check);
  493. queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
  494. msecs_to_jiffies(1000));
  495. dev_set_drvdata(&pdev->dev, priv);
  496. provider = devm_of_phy_provider_register(&pdev->dev, lynx_28g_xlate);
  497. return PTR_ERR_OR_ZERO(provider);
  498. }
  499. static void lynx_28g_remove(struct platform_device *pdev)
  500. {
  501. struct device *dev = &pdev->dev;
  502. struct lynx_28g_priv *priv = dev_get_drvdata(dev);
  503. cancel_delayed_work_sync(&priv->cdr_check);
  504. }
  505. static const struct of_device_id lynx_28g_of_match_table[] = {
  506. { .compatible = "fsl,lynx-28g" },
  507. { },
  508. };
  509. MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
  510. static struct platform_driver lynx_28g_driver = {
  511. .probe = lynx_28g_probe,
  512. .remove_new = lynx_28g_remove,
  513. .driver = {
  514. .name = "lynx-28g",
  515. .of_match_table = lynx_28g_of_match_table,
  516. },
  517. };
  518. module_platform_driver(lynx_28g_driver);
  519. MODULE_AUTHOR("Ioana Ciornei <[email protected]>");
  520. MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs");
  521. MODULE_LICENSE("GPL v2");