phy-ocelot-serdes.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /*
  3. * SerDes PHY driver for Microsemi Ocelot
  4. *
  5. * Copyright (c) 2018 Microsemi
  6. *
  7. */
  8. #include <linux/err.h>
  9. #include <linux/mfd/syscon.h>
  10. #include <linux/module.h>
  11. #include <linux/of.h>
  12. #include <linux/of_platform.h>
  13. #include <linux/phy.h>
  14. #include <linux/phy/phy.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/regmap.h>
  17. #include <soc/mscc/ocelot_hsio.h>
  18. #include <dt-bindings/phy/phy-ocelot-serdes.h>
  19. struct serdes_ctrl {
  20. struct regmap *regs;
  21. struct device *dev;
  22. struct phy *phys[SERDES_MAX];
  23. };
  24. struct serdes_macro {
  25. u8 idx;
  26. /* Not used when in QSGMII or PCIe mode */
  27. int port;
  28. struct serdes_ctrl *ctrl;
  29. };
  30. #define MCB_S6G_CFG_TIMEOUT 50
  31. static int __serdes_write_mcb_s6g(struct regmap *regmap, u8 macro, u32 op)
  32. {
  33. unsigned int regval = 0;
  34. regmap_write(regmap, HSIO_MCB_S6G_ADDR_CFG, op |
  35. HSIO_MCB_S6G_ADDR_CFG_SERDES6G_ADDR(BIT(macro)));
  36. return regmap_read_poll_timeout(regmap, HSIO_MCB_S6G_ADDR_CFG, regval,
  37. (regval & op) != op, 100,
  38. MCB_S6G_CFG_TIMEOUT * 1000);
  39. }
  40. static int serdes_commit_mcb_s6g(struct regmap *regmap, u8 macro)
  41. {
  42. return __serdes_write_mcb_s6g(regmap, macro,
  43. HSIO_MCB_S6G_ADDR_CFG_SERDES6G_WR_ONE_SHOT);
  44. }
  45. static int serdes_update_mcb_s6g(struct regmap *regmap, u8 macro)
  46. {
  47. return __serdes_write_mcb_s6g(regmap, macro,
  48. HSIO_MCB_S6G_ADDR_CFG_SERDES6G_RD_ONE_SHOT);
  49. }
  50. static int serdes_init_s6g(struct regmap *regmap, u8 serdes, int mode)
  51. {
  52. u32 pll_fsm_ctrl_data;
  53. u32 ob_ena1v_mode;
  54. u32 des_bw_ana;
  55. u32 ob_ena_cas;
  56. u32 if_mode;
  57. u32 ob_lev;
  58. u32 qrate;
  59. int ret;
  60. if (mode == PHY_INTERFACE_MODE_QSGMII) {
  61. pll_fsm_ctrl_data = 120;
  62. ob_ena1v_mode = 0;
  63. ob_ena_cas = 0;
  64. des_bw_ana = 5;
  65. ob_lev = 24;
  66. if_mode = 3;
  67. qrate = 0;
  68. } else {
  69. pll_fsm_ctrl_data = 60;
  70. ob_ena1v_mode = 1;
  71. ob_ena_cas = 2;
  72. des_bw_ana = 3;
  73. ob_lev = 48;
  74. if_mode = 1;
  75. qrate = 1;
  76. }
  77. ret = serdes_update_mcb_s6g(regmap, serdes);
  78. if (ret)
  79. return ret;
  80. /* Test pattern */
  81. regmap_update_bits(regmap, HSIO_S6G_COMMON_CFG,
  82. HSIO_S6G_COMMON_CFG_SYS_RST, 0);
  83. regmap_update_bits(regmap, HSIO_S6G_PLL_CFG,
  84. HSIO_S6G_PLL_CFG_PLL_FSM_ENA, 0);
  85. regmap_update_bits(regmap, HSIO_S6G_IB_CFG,
  86. HSIO_S6G_IB_CFG_IB_SIG_DET_ENA |
  87. HSIO_S6G_IB_CFG_IB_REG_ENA |
  88. HSIO_S6G_IB_CFG_IB_SAM_ENA |
  89. HSIO_S6G_IB_CFG_IB_EQZ_ENA |
  90. HSIO_S6G_IB_CFG_IB_CONCUR |
  91. HSIO_S6G_IB_CFG_IB_CAL_ENA,
  92. HSIO_S6G_IB_CFG_IB_SIG_DET_ENA |
  93. HSIO_S6G_IB_CFG_IB_REG_ENA |
  94. HSIO_S6G_IB_CFG_IB_SAM_ENA |
  95. HSIO_S6G_IB_CFG_IB_EQZ_ENA |
  96. HSIO_S6G_IB_CFG_IB_CONCUR);
  97. regmap_update_bits(regmap, HSIO_S6G_IB_CFG1,
  98. HSIO_S6G_IB_CFG1_IB_FRC_OFFSET |
  99. HSIO_S6G_IB_CFG1_IB_FRC_LP |
  100. HSIO_S6G_IB_CFG1_IB_FRC_MID |
  101. HSIO_S6G_IB_CFG1_IB_FRC_HP |
  102. HSIO_S6G_IB_CFG1_IB_FILT_OFFSET |
  103. HSIO_S6G_IB_CFG1_IB_FILT_LP |
  104. HSIO_S6G_IB_CFG1_IB_FILT_MID |
  105. HSIO_S6G_IB_CFG1_IB_FILT_HP,
  106. HSIO_S6G_IB_CFG1_IB_FILT_OFFSET |
  107. HSIO_S6G_IB_CFG1_IB_FILT_HP |
  108. HSIO_S6G_IB_CFG1_IB_FILT_LP |
  109. HSIO_S6G_IB_CFG1_IB_FILT_MID);
  110. regmap_update_bits(regmap, HSIO_S6G_IB_CFG2,
  111. HSIO_S6G_IB_CFG2_IB_UREG_M,
  112. HSIO_S6G_IB_CFG2_IB_UREG(4));
  113. regmap_update_bits(regmap, HSIO_S6G_IB_CFG3,
  114. HSIO_S6G_IB_CFG3_IB_INI_OFFSET_M |
  115. HSIO_S6G_IB_CFG3_IB_INI_LP_M |
  116. HSIO_S6G_IB_CFG3_IB_INI_MID_M |
  117. HSIO_S6G_IB_CFG3_IB_INI_HP_M,
  118. HSIO_S6G_IB_CFG3_IB_INI_OFFSET(31) |
  119. HSIO_S6G_IB_CFG3_IB_INI_LP(1) |
  120. HSIO_S6G_IB_CFG3_IB_INI_MID(31) |
  121. HSIO_S6G_IB_CFG3_IB_INI_HP(0));
  122. regmap_update_bits(regmap, HSIO_S6G_MISC_CFG,
  123. HSIO_S6G_MISC_CFG_LANE_RST,
  124. HSIO_S6G_MISC_CFG_LANE_RST);
  125. ret = serdes_commit_mcb_s6g(regmap, serdes);
  126. if (ret)
  127. return ret;
  128. /* OB + DES + IB + SER CFG */
  129. regmap_update_bits(regmap, HSIO_S6G_OB_CFG,
  130. HSIO_S6G_OB_CFG_OB_IDLE |
  131. HSIO_S6G_OB_CFG_OB_ENA1V_MODE |
  132. HSIO_S6G_OB_CFG_OB_POST0_M |
  133. HSIO_S6G_OB_CFG_OB_PREC_M,
  134. (ob_ena1v_mode ? HSIO_S6G_OB_CFG_OB_ENA1V_MODE : 0) |
  135. HSIO_S6G_OB_CFG_OB_POST0(0) |
  136. HSIO_S6G_OB_CFG_OB_PREC(0));
  137. regmap_update_bits(regmap, HSIO_S6G_OB_CFG1,
  138. HSIO_S6G_OB_CFG1_OB_ENA_CAS_M |
  139. HSIO_S6G_OB_CFG1_OB_LEV_M,
  140. HSIO_S6G_OB_CFG1_OB_LEV(ob_lev) |
  141. HSIO_S6G_OB_CFG1_OB_ENA_CAS(ob_ena_cas));
  142. regmap_update_bits(regmap, HSIO_S6G_DES_CFG,
  143. HSIO_S6G_DES_CFG_DES_PHS_CTRL_M |
  144. HSIO_S6G_DES_CFG_DES_CPMD_SEL_M |
  145. HSIO_S6G_DES_CFG_DES_BW_ANA_M,
  146. HSIO_S6G_DES_CFG_DES_PHS_CTRL(2) |
  147. HSIO_S6G_DES_CFG_DES_CPMD_SEL(0) |
  148. HSIO_S6G_DES_CFG_DES_BW_ANA(des_bw_ana));
  149. regmap_update_bits(regmap, HSIO_S6G_IB_CFG,
  150. HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL_M |
  151. HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET_M,
  152. HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET(0) |
  153. HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL(0));
  154. regmap_update_bits(regmap, HSIO_S6G_IB_CFG1,
  155. HSIO_S6G_IB_CFG1_IB_TSDET_M,
  156. HSIO_S6G_IB_CFG1_IB_TSDET(16));
  157. regmap_update_bits(regmap, HSIO_S6G_SER_CFG,
  158. HSIO_S6G_SER_CFG_SER_ALISEL_M |
  159. HSIO_S6G_SER_CFG_SER_ENALI,
  160. HSIO_S6G_SER_CFG_SER_ALISEL(0));
  161. regmap_update_bits(regmap, HSIO_S6G_PLL_CFG,
  162. HSIO_S6G_PLL_CFG_PLL_DIV4 |
  163. HSIO_S6G_PLL_CFG_PLL_ENA_ROT |
  164. HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA_M |
  165. HSIO_S6G_PLL_CFG_PLL_ROT_DIR |
  166. HSIO_S6G_PLL_CFG_PLL_ROT_FRQ,
  167. HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA
  168. (pll_fsm_ctrl_data));
  169. regmap_update_bits(regmap, HSIO_S6G_COMMON_CFG,
  170. HSIO_S6G_COMMON_CFG_SYS_RST |
  171. HSIO_S6G_COMMON_CFG_ENA_LANE |
  172. HSIO_S6G_COMMON_CFG_PWD_RX |
  173. HSIO_S6G_COMMON_CFG_PWD_TX |
  174. HSIO_S6G_COMMON_CFG_HRATE |
  175. HSIO_S6G_COMMON_CFG_QRATE |
  176. HSIO_S6G_COMMON_CFG_ENA_ELOOP |
  177. HSIO_S6G_COMMON_CFG_ENA_FLOOP |
  178. HSIO_S6G_COMMON_CFG_IF_MODE_M,
  179. HSIO_S6G_COMMON_CFG_SYS_RST |
  180. HSIO_S6G_COMMON_CFG_ENA_LANE |
  181. (qrate ? HSIO_S6G_COMMON_CFG_QRATE : 0) |
  182. HSIO_S6G_COMMON_CFG_IF_MODE(if_mode));
  183. regmap_update_bits(regmap, HSIO_S6G_MISC_CFG,
  184. HSIO_S6G_MISC_CFG_LANE_RST |
  185. HSIO_S6G_MISC_CFG_DES_100FX_CPMD_ENA |
  186. HSIO_S6G_MISC_CFG_RX_LPI_MODE_ENA |
  187. HSIO_S6G_MISC_CFG_TX_LPI_MODE_ENA,
  188. HSIO_S6G_MISC_CFG_LANE_RST |
  189. HSIO_S6G_MISC_CFG_RX_LPI_MODE_ENA);
  190. ret = serdes_commit_mcb_s6g(regmap, serdes);
  191. if (ret)
  192. return ret;
  193. regmap_update_bits(regmap, HSIO_S6G_PLL_CFG,
  194. HSIO_S6G_PLL_CFG_PLL_FSM_ENA,
  195. HSIO_S6G_PLL_CFG_PLL_FSM_ENA);
  196. ret = serdes_commit_mcb_s6g(regmap, serdes);
  197. if (ret)
  198. return ret;
  199. /* Wait for PLL bringup */
  200. msleep(20);
  201. regmap_update_bits(regmap, HSIO_S6G_IB_CFG,
  202. HSIO_S6G_IB_CFG_IB_CAL_ENA,
  203. HSIO_S6G_IB_CFG_IB_CAL_ENA);
  204. regmap_update_bits(regmap, HSIO_S6G_MISC_CFG,
  205. HSIO_S6G_MISC_CFG_LANE_RST, 0);
  206. ret = serdes_commit_mcb_s6g(regmap, serdes);
  207. if (ret)
  208. return ret;
  209. /* Wait for calibration */
  210. msleep(60);
  211. regmap_update_bits(regmap, HSIO_S6G_IB_CFG,
  212. HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET_M |
  213. HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL_M,
  214. HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET(0) |
  215. HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL(7));
  216. regmap_update_bits(regmap, HSIO_S6G_IB_CFG1,
  217. HSIO_S6G_IB_CFG1_IB_TSDET_M,
  218. HSIO_S6G_IB_CFG1_IB_TSDET(3));
  219. /* IB CFG */
  220. return 0;
  221. }
  222. #define MCB_S1G_CFG_TIMEOUT 50
  223. static int __serdes_write_mcb_s1g(struct regmap *regmap, u8 macro, u32 op)
  224. {
  225. unsigned int regval;
  226. regmap_write(regmap, HSIO_MCB_S1G_ADDR_CFG, op |
  227. HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR(BIT(macro)));
  228. return regmap_read_poll_timeout(regmap, HSIO_MCB_S1G_ADDR_CFG, regval,
  229. (regval & op) != op, 100,
  230. MCB_S1G_CFG_TIMEOUT * 1000);
  231. }
  232. static int serdes_commit_mcb_s1g(struct regmap *regmap, u8 macro)
  233. {
  234. return __serdes_write_mcb_s1g(regmap, macro,
  235. HSIO_MCB_S1G_ADDR_CFG_SERDES1G_WR_ONE_SHOT);
  236. }
  237. static int serdes_update_mcb_s1g(struct regmap *regmap, u8 macro)
  238. {
  239. return __serdes_write_mcb_s1g(regmap, macro,
  240. HSIO_MCB_S1G_ADDR_CFG_SERDES1G_RD_ONE_SHOT);
  241. }
  242. static int serdes_init_s1g(struct regmap *regmap, u8 serdes)
  243. {
  244. int ret;
  245. ret = serdes_update_mcb_s1g(regmap, serdes);
  246. if (ret)
  247. return ret;
  248. regmap_update_bits(regmap, HSIO_S1G_COMMON_CFG,
  249. HSIO_S1G_COMMON_CFG_SYS_RST |
  250. HSIO_S1G_COMMON_CFG_ENA_LANE |
  251. HSIO_S1G_COMMON_CFG_ENA_ELOOP |
  252. HSIO_S1G_COMMON_CFG_ENA_FLOOP,
  253. HSIO_S1G_COMMON_CFG_ENA_LANE);
  254. regmap_update_bits(regmap, HSIO_S1G_PLL_CFG,
  255. HSIO_S1G_PLL_CFG_PLL_FSM_ENA |
  256. HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_M,
  257. HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA(200) |
  258. HSIO_S1G_PLL_CFG_PLL_FSM_ENA);
  259. regmap_update_bits(regmap, HSIO_S1G_MISC_CFG,
  260. HSIO_S1G_MISC_CFG_DES_100FX_CPMD_ENA |
  261. HSIO_S1G_MISC_CFG_LANE_RST,
  262. HSIO_S1G_MISC_CFG_LANE_RST);
  263. ret = serdes_commit_mcb_s1g(regmap, serdes);
  264. if (ret)
  265. return ret;
  266. regmap_update_bits(regmap, HSIO_S1G_COMMON_CFG,
  267. HSIO_S1G_COMMON_CFG_SYS_RST,
  268. HSIO_S1G_COMMON_CFG_SYS_RST);
  269. regmap_update_bits(regmap, HSIO_S1G_MISC_CFG,
  270. HSIO_S1G_MISC_CFG_LANE_RST, 0);
  271. ret = serdes_commit_mcb_s1g(regmap, serdes);
  272. if (ret)
  273. return ret;
  274. return 0;
  275. }
  276. struct serdes_mux {
  277. u8 idx;
  278. u8 port;
  279. enum phy_mode mode;
  280. int submode;
  281. u32 mask;
  282. u32 mux;
  283. };
  284. #define SERDES_MUX(_idx, _port, _mode, _submode, _mask, _mux) { \
  285. .idx = _idx, \
  286. .port = _port, \
  287. .mode = _mode, \
  288. .submode = _submode, \
  289. .mask = _mask, \
  290. .mux = _mux, \
  291. }
  292. #define SERDES_MUX_SGMII(i, p, m, c) \
  293. SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c)
  294. #define SERDES_MUX_QSGMII(i, p, m, c) \
  295. SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c)
  296. static const struct serdes_mux ocelot_serdes_muxes[] = {
  297. SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0),
  298. SERDES_MUX_SGMII(SERDES1G(1), 1, HSIO_HW_CFG_DEV1G_5_MODE, 0),
  299. SERDES_MUX_SGMII(SERDES1G(1), 5, HSIO_HW_CFG_QSGMII_ENA |
  300. HSIO_HW_CFG_DEV1G_5_MODE, HSIO_HW_CFG_DEV1G_5_MODE),
  301. SERDES_MUX_SGMII(SERDES1G(2), 2, HSIO_HW_CFG_DEV1G_4_MODE, 0),
  302. SERDES_MUX_SGMII(SERDES1G(2), 4, HSIO_HW_CFG_QSGMII_ENA |
  303. HSIO_HW_CFG_DEV1G_4_MODE, HSIO_HW_CFG_DEV1G_4_MODE),
  304. SERDES_MUX_SGMII(SERDES1G(3), 3, HSIO_HW_CFG_DEV1G_6_MODE, 0),
  305. SERDES_MUX_SGMII(SERDES1G(3), 6, HSIO_HW_CFG_QSGMII_ENA |
  306. HSIO_HW_CFG_DEV1G_6_MODE, HSIO_HW_CFG_DEV1G_6_MODE),
  307. SERDES_MUX_SGMII(SERDES1G(4), 4, HSIO_HW_CFG_QSGMII_ENA |
  308. HSIO_HW_CFG_DEV1G_4_MODE | HSIO_HW_CFG_DEV1G_9_MODE,
  309. 0),
  310. SERDES_MUX_SGMII(SERDES1G(4), 9, HSIO_HW_CFG_DEV1G_4_MODE |
  311. HSIO_HW_CFG_DEV1G_9_MODE, HSIO_HW_CFG_DEV1G_4_MODE |
  312. HSIO_HW_CFG_DEV1G_9_MODE),
  313. SERDES_MUX_SGMII(SERDES1G(5), 5, HSIO_HW_CFG_QSGMII_ENA |
  314. HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE,
  315. 0),
  316. SERDES_MUX_SGMII(SERDES1G(5), 10, HSIO_HW_CFG_PCIE_ENA |
  317. HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE,
  318. HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE),
  319. SERDES_MUX_QSGMII(SERDES6G(0), 4, HSIO_HW_CFG_QSGMII_ENA,
  320. HSIO_HW_CFG_QSGMII_ENA),
  321. SERDES_MUX_QSGMII(SERDES6G(0), 5, HSIO_HW_CFG_QSGMII_ENA,
  322. HSIO_HW_CFG_QSGMII_ENA),
  323. SERDES_MUX_QSGMII(SERDES6G(0), 6, HSIO_HW_CFG_QSGMII_ENA,
  324. HSIO_HW_CFG_QSGMII_ENA),
  325. SERDES_MUX_SGMII(SERDES6G(0), 7, HSIO_HW_CFG_QSGMII_ENA, 0),
  326. SERDES_MUX_QSGMII(SERDES6G(0), 7, HSIO_HW_CFG_QSGMII_ENA,
  327. HSIO_HW_CFG_QSGMII_ENA),
  328. SERDES_MUX_SGMII(SERDES6G(1), 8, 0, 0),
  329. SERDES_MUX_SGMII(SERDES6G(2), 10, HSIO_HW_CFG_PCIE_ENA |
  330. HSIO_HW_CFG_DEV2G5_10_MODE, 0),
  331. SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, 0, HSIO_HW_CFG_PCIE_ENA,
  332. HSIO_HW_CFG_PCIE_ENA),
  333. };
  334. static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
  335. {
  336. struct serdes_macro *macro = phy_get_drvdata(phy);
  337. unsigned int i;
  338. int ret;
  339. /* As of now only PHY_MODE_ETHERNET is supported */
  340. if (mode != PHY_MODE_ETHERNET)
  341. return -EOPNOTSUPP;
  342. for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) {
  343. if (macro->idx != ocelot_serdes_muxes[i].idx ||
  344. mode != ocelot_serdes_muxes[i].mode ||
  345. submode != ocelot_serdes_muxes[i].submode)
  346. continue;
  347. if (submode != PHY_INTERFACE_MODE_QSGMII &&
  348. macro->port != ocelot_serdes_muxes[i].port)
  349. continue;
  350. ret = regmap_update_bits(macro->ctrl->regs, HSIO_HW_CFG,
  351. ocelot_serdes_muxes[i].mask,
  352. ocelot_serdes_muxes[i].mux);
  353. if (ret)
  354. return ret;
  355. if (macro->idx <= SERDES1G_MAX)
  356. return serdes_init_s1g(macro->ctrl->regs, macro->idx);
  357. else if (macro->idx <= SERDES6G_MAX)
  358. return serdes_init_s6g(macro->ctrl->regs,
  359. macro->idx - (SERDES1G_MAX + 1),
  360. ocelot_serdes_muxes[i].submode);
  361. /* PCIe not supported yet */
  362. return -EOPNOTSUPP;
  363. }
  364. return -EINVAL;
  365. }
  366. static const struct phy_ops serdes_ops = {
  367. .set_mode = serdes_set_mode,
  368. .owner = THIS_MODULE,
  369. };
  370. static struct phy *serdes_simple_xlate(struct device *dev,
  371. struct of_phandle_args *args)
  372. {
  373. struct serdes_ctrl *ctrl = dev_get_drvdata(dev);
  374. unsigned int port, idx, i;
  375. if (args->args_count != 2)
  376. return ERR_PTR(-EINVAL);
  377. port = args->args[0];
  378. idx = args->args[1];
  379. for (i = 0; i < SERDES_MAX; i++) {
  380. struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]);
  381. if (idx != macro->idx)
  382. continue;
  383. /* SERDES6G(0) is the only SerDes capable of QSGMII */
  384. if (idx != SERDES6G(0) && macro->port >= 0)
  385. return ERR_PTR(-EBUSY);
  386. macro->port = port;
  387. return ctrl->phys[i];
  388. }
  389. return ERR_PTR(-ENODEV);
  390. }
  391. static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx, struct phy **phy)
  392. {
  393. struct serdes_macro *macro;
  394. *phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops);
  395. if (IS_ERR(*phy))
  396. return PTR_ERR(*phy);
  397. macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL);
  398. if (!macro)
  399. return -ENOMEM;
  400. macro->idx = idx;
  401. macro->ctrl = ctrl;
  402. macro->port = -1;
  403. phy_set_drvdata(*phy, macro);
  404. return 0;
  405. }
  406. static int serdes_probe(struct platform_device *pdev)
  407. {
  408. struct phy_provider *provider;
  409. struct serdes_ctrl *ctrl;
  410. unsigned int i;
  411. int ret;
  412. ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
  413. if (!ctrl)
  414. return -ENOMEM;
  415. ctrl->dev = &pdev->dev;
  416. ctrl->regs = syscon_node_to_regmap(pdev->dev.parent->of_node);
  417. if (IS_ERR(ctrl->regs))
  418. return PTR_ERR(ctrl->regs);
  419. for (i = 0; i < SERDES_MAX; i++) {
  420. ret = serdes_phy_create(ctrl, i, &ctrl->phys[i]);
  421. if (ret)
  422. return ret;
  423. }
  424. dev_set_drvdata(&pdev->dev, ctrl);
  425. provider = devm_of_phy_provider_register(ctrl->dev,
  426. serdes_simple_xlate);
  427. return PTR_ERR_OR_ZERO(provider);
  428. }
  429. static const struct of_device_id serdes_ids[] = {
  430. { .compatible = "mscc,vsc7514-serdes", },
  431. {},
  432. };
  433. MODULE_DEVICE_TABLE(of, serdes_ids);
  434. static struct platform_driver mscc_ocelot_serdes = {
  435. .probe = serdes_probe,
  436. .driver = {
  437. .name = "mscc,ocelot-serdes",
  438. .of_match_table = of_match_ptr(serdes_ids),
  439. },
  440. };
  441. module_platform_driver(mscc_ocelot_serdes);
  442. MODULE_AUTHOR("Quentin Schulz <[email protected]>");
  443. MODULE_DESCRIPTION("SerDes driver for Microsemi Ocelot");
  444. MODULE_LICENSE("Dual MIT/GPL");