mscc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. // SPDX-License-Identifier: MIT
  2. /*
  3. * Microsemi PHY drivers
  4. *
  5. *
  6. * Copyright (c) 2016 Microsemi Corporation
  7. *
  8. * Author: John Haechten
  9. *
  10. */
  11. #include <miiphy.h>
  12. #include <bitfield.h>
  13. /* Microsemi PHY ID's */
  14. #define PHY_ID_VSC8530 0x00070560
  15. #define PHY_ID_VSC8531 0x00070570
  16. #define PHY_ID_VSC8540 0x00070760
  17. #define PHY_ID_VSC8541 0x00070770
  18. /* Microsemi VSC85xx PHY Register Pages */
  19. #define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */
  20. #define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */
  21. #define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */
  22. #define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */
  23. #define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */
  24. #define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */
  25. #define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */
  26. #define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */
  27. #define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */
  28. /* Std Page Register 28 - PHY AUX Control/Status */
  29. #define MIIM_AUX_CNTRL_STAT_REG 28
  30. #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004)
  31. #define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020)
  32. #define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018)
  33. #define MIIM_AUX_CNTRL_STAT_SPEED_POS (3)
  34. #define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0)
  35. #define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1)
  36. #define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2)
  37. /* Std Page Register 23 - Extended PHY CTRL_1 */
  38. #define MSCC_PHY_EXT_PHY_CNTL_1_REG 23
  39. #define MAC_IF_SELECTION_MASK (0x1800)
  40. #define MAC_IF_SELECTION_GMII (0)
  41. #define MAC_IF_SELECTION_RMII (1)
  42. #define MAC_IF_SELECTION_RGMII (2)
  43. #define MAC_IF_SELECTION_POS (11)
  44. #define MAC_IF_SELECTION_WIDTH (2)
  45. /* Extended Page 2 Register 20E2 */
  46. #define MSCC_PHY_RGMII_CNTL_REG 20
  47. #define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000)
  48. #define RX_CLK_OUT_MASK (0x0800)
  49. #define RX_CLK_OUT_POS (11)
  50. #define RX_CLK_OUT_WIDTH (1)
  51. #define RX_CLK_OUT_NORMAL (0)
  52. #define RX_CLK_OUT_DISABLE (1)
  53. #define RGMII_RX_CLK_DELAY_POS (4)
  54. #define RGMII_RX_CLK_DELAY_WIDTH (3)
  55. #define RGMII_RX_CLK_DELAY_MASK (0x0070)
  56. #define RGMII_TX_CLK_DELAY_POS (0)
  57. #define RGMII_TX_CLK_DELAY_WIDTH (3)
  58. #define RGMII_TX_CLK_DELAY_MASK (0x0007)
  59. /* Extended Page 2 Register 27E2 */
  60. #define MSCC_PHY_WOL_MAC_CONTROL 27
  61. #define EDGE_RATE_CNTL_POS (5)
  62. #define EDGE_RATE_CNTL_WIDTH (3)
  63. #define EDGE_RATE_CNTL_MASK (0x00E0)
  64. #define RMII_CLK_OUT_ENABLE_POS (4)
  65. #define RMII_CLK_OUT_ENABLE_WIDTH (1)
  66. #define RMII_CLK_OUT_ENABLE_MASK (0x10)
  67. /* Token Ring Page 0x52B5 Registers */
  68. #define MSCC_PHY_REG_TR_ADDR_16 16
  69. #define MSCC_PHY_REG_TR_DATA_17 17
  70. #define MSCC_PHY_REG_TR_DATA_18 18
  71. /* Token Ring - Read Value in */
  72. #define MSCC_PHY_TR_16_READ (0xA000)
  73. /* Token Ring - Write Value out */
  74. #define MSCC_PHY_TR_16_WRITE (0x8000)
  75. /* Token Ring Registers */
  76. #define MSCC_PHY_TR_LINKDETCTRL_POS (3)
  77. #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2)
  78. #define MSCC_PHY_TR_LINKDETCTRL_VAL (3)
  79. #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018)
  80. #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8)
  81. #define MSCC_PHY_TR_VGATHRESH100_POS (0)
  82. #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7)
  83. #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018)
  84. #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f)
  85. #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4)
  86. #define MSCC_PHY_TR_VGAGAIN10_U_POS (0)
  87. #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1)
  88. #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001)
  89. #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0)
  90. #define MSCC_PHY_TR_VGAGAIN10_L_POS (12)
  91. #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4)
  92. #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000)
  93. #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001)
  94. #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92)
  95. /* General Timeout Values */
  96. #define MSCC_PHY_RESET_TIMEOUT (100)
  97. #define MSCC_PHY_MICRO_TIMEOUT (500)
  98. /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
  99. VSC_PHY_RGMII_DELAY_200_PS,
  100. VSC_PHY_RGMII_DELAY_800_PS,
  101. VSC_PHY_RGMII_DELAY_1100_PS,
  102. VSC_PHY_RGMII_DELAY_1700_PS,
  103. VSC_PHY_RGMII_DELAY_2000_PS,
  104. VSC_PHY_RGMII_DELAY_2300_PS,
  105. VSC_PHY_RGMII_DELAY_2600_PS,
  106. VSC_PHY_RGMII_DELAY_3400_PS,
  107. };
  108. /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
  109. vsc_phy_clk_slew {
  110. VSC_PHY_CLK_SLEW_RATE_0,
  111. VSC_PHY_CLK_SLEW_RATE_1,
  112. VSC_PHY_CLK_SLEW_RATE_2,
  113. VSC_PHY_CLK_SLEW_RATE_3,
  114. VSC_PHY_CLK_SLEW_RATE_4,
  115. VSC_PHY_CLK_SLEW_RATE_5,
  116. VSC_PHY_CLK_SLEW_RATE_6,
  117. VSC_PHY_CLK_SLEW_RATE_7,
  118. };
  119. static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
  120. {
  121. u16 reg_val;
  122. /* Set to Access Token Ring Registers */
  123. phy_write(phydev, MDIO_DEVAD_NONE,
  124. MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  125. /* Update LinkDetectCtrl default to optimized values */
  126. /* Determined during Silicon Validation Testing */
  127. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  128. (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
  129. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
  130. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
  131. MSCC_PHY_TR_LINKDETCTRL_WIDTH,
  132. MSCC_PHY_TR_LINKDETCTRL_VAL);
  133. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
  134. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  135. (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
  136. /* Update VgaThresh100 defaults to optimized values */
  137. /* Determined during Silicon Validation Testing */
  138. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  139. (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
  140. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
  141. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
  142. MSCC_PHY_TR_VGATHRESH100_WIDTH,
  143. MSCC_PHY_TR_VGATHRESH100_VAL);
  144. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
  145. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  146. (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
  147. /* Update VgaGain10 defaults to optimized values */
  148. /* Determined during Silicon Validation Testing */
  149. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  150. (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
  151. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
  152. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
  153. MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
  154. MSCC_PHY_TR_VGAGAIN10_U_VAL);
  155. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
  156. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
  157. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
  158. MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
  159. MSCC_PHY_TR_VGAGAIN10_L_VAL);
  160. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
  161. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  162. (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
  163. /* Set back to Access Standard Page Registers */
  164. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  165. MSCC_PHY_PAGE_STD);
  166. return 0;
  167. }
  168. static int mscc_parse_status(struct phy_device *phydev)
  169. {
  170. u16 speed;
  171. u16 mii_reg;
  172. mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
  173. if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
  174. phydev->duplex = DUPLEX_FULL;
  175. else
  176. phydev->duplex = DUPLEX_HALF;
  177. speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
  178. speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
  179. switch (speed) {
  180. case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
  181. phydev->speed = SPEED_1000;
  182. break;
  183. case MIIM_AUX_CNTRL_STAT_SPEED_100M:
  184. phydev->speed = SPEED_100;
  185. break;
  186. case MIIM_AUX_CNTRL_STAT_SPEED_10M:
  187. phydev->speed = SPEED_10;
  188. break;
  189. default:
  190. phydev->speed = SPEED_10;
  191. break;
  192. }
  193. return 0;
  194. }
  195. static int mscc_startup(struct phy_device *phydev)
  196. {
  197. int retval;
  198. retval = genphy_update_link(phydev);
  199. if (retval)
  200. return retval;
  201. return mscc_parse_status(phydev);
  202. }
  203. static int mscc_phy_soft_reset(struct phy_device *phydev)
  204. {
  205. int retval = 0;
  206. u16 timeout = MSCC_PHY_RESET_TIMEOUT;
  207. u16 reg_val = 0;
  208. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  209. MSCC_PHY_PAGE_STD);
  210. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  211. phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
  212. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  213. while ((reg_val & BMCR_RESET) && (timeout > 0)) {
  214. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  215. timeout--;
  216. udelay(1000); /* 1 ms */
  217. }
  218. if (timeout == 0) {
  219. printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
  220. phydev->interface);
  221. retval = -ETIME;
  222. }
  223. return retval;
  224. }
  225. static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
  226. {
  227. u16 reg_val = 0;
  228. u16 mac_if = 0;
  229. u16 rx_clk_out = 0;
  230. /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
  231. /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
  232. /* Setup MAC Configuration */
  233. switch (phydev->interface) {
  234. case PHY_INTERFACE_MODE_MII:
  235. case PHY_INTERFACE_MODE_GMII:
  236. /* Set Reg23.12:11=0 */
  237. mac_if = MAC_IF_SELECTION_GMII;
  238. /* Set Reg20E2.11=1 */
  239. rx_clk_out = RX_CLK_OUT_DISABLE;
  240. break;
  241. case PHY_INTERFACE_MODE_RMII:
  242. /* Set Reg23.12:11=1 */
  243. mac_if = MAC_IF_SELECTION_RMII;
  244. /* Set Reg20E2.11=0 */
  245. rx_clk_out = RX_CLK_OUT_NORMAL;
  246. break;
  247. case PHY_INTERFACE_MODE_RGMII:
  248. /* Set Reg23.12:11=2 */
  249. mac_if = MAC_IF_SELECTION_RGMII;
  250. /* Set Reg20E2.11=0 */
  251. rx_clk_out = RX_CLK_OUT_NORMAL;
  252. break;
  253. default:
  254. printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
  255. phydev->interface);
  256. return -EINVAL;
  257. }
  258. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  259. MSCC_PHY_PAGE_STD);
  260. reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
  261. MSCC_PHY_EXT_PHY_CNTL_1_REG);
  262. /* Set MAC i/f bits Reg23.12:11 */
  263. reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
  264. MAC_IF_SELECTION_WIDTH, mac_if);
  265. /* Update Reg23.12:11 */
  266. phy_write(phydev, MDIO_DEVAD_NONE,
  267. MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
  268. /* Setup ExtPg_2 Register Access */
  269. phy_write(phydev, MDIO_DEVAD_NONE,
  270. MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
  271. /* Read Reg20E2 */
  272. reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
  273. MSCC_PHY_RGMII_CNTL_REG);
  274. reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
  275. RX_CLK_OUT_WIDTH, rx_clk_out);
  276. /* Update Reg20E2.11 */
  277. phy_write(phydev, MDIO_DEVAD_NONE,
  278. MSCC_PHY_RGMII_CNTL_REG, reg_val);
  279. /* Before leaving - Change back to Std Page Register Access */
  280. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  281. MSCC_PHY_PAGE_STD);
  282. return 0;
  283. }
  284. static int vsc8531_config(struct phy_device *phydev)
  285. {
  286. int retval = -EINVAL;
  287. u16 reg_val;
  288. u16 rmii_clk_out;
  289. enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
  290. enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
  291. enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
  292. /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
  293. mscc_vsc8531_vsc8541_init_scripts(phydev);
  294. /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
  295. switch (phydev->interface) {
  296. case PHY_INTERFACE_MODE_RMII:
  297. case PHY_INTERFACE_MODE_RGMII:
  298. retval = vsc8531_vsc8541_mac_config(phydev);
  299. if (retval != 0)
  300. return retval;
  301. retval = mscc_phy_soft_reset(phydev);
  302. if (retval != 0)
  303. return retval;
  304. break;
  305. default:
  306. printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
  307. phydev->interface);
  308. return -EINVAL;
  309. }
  310. /* Default RMII Clk Output to 0=OFF/1=ON */
  311. rmii_clk_out = 0;
  312. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  313. MSCC_PHY_PAGE_EXT2);
  314. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
  315. /* Reg20E2 - Update RGMII RX_Clk Skews. */
  316. reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
  317. RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
  318. /* Reg20E2 - Update RGMII TX_Clk Skews. */
  319. reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
  320. RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
  321. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
  322. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
  323. /* Reg27E2 - Update Clk Slew Rate. */
  324. reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
  325. EDGE_RATE_CNTL_WIDTH, edge_rate);
  326. /* Reg27E2 - Update RMII Clk Out. */
  327. reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
  328. RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
  329. /* Update Reg27E2 */
  330. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
  331. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  332. MSCC_PHY_PAGE_STD);
  333. return genphy_config_aneg(phydev);
  334. }
  335. static int vsc8541_config(struct phy_device *phydev)
  336. {
  337. int retval = -EINVAL;
  338. u16 reg_val;
  339. u16 rmii_clk_out;
  340. enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
  341. enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
  342. enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
  343. /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
  344. mscc_vsc8531_vsc8541_init_scripts(phydev);
  345. /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
  346. switch (phydev->interface) {
  347. case PHY_INTERFACE_MODE_MII:
  348. case PHY_INTERFACE_MODE_GMII:
  349. case PHY_INTERFACE_MODE_RMII:
  350. case PHY_INTERFACE_MODE_RGMII:
  351. retval = vsc8531_vsc8541_mac_config(phydev);
  352. if (retval != 0)
  353. return retval;
  354. retval = mscc_phy_soft_reset(phydev);
  355. if (retval != 0)
  356. return retval;
  357. break;
  358. default:
  359. printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
  360. phydev->interface);
  361. return -EINVAL;
  362. }
  363. /* Default RMII Clk Output to 0=OFF/1=ON */
  364. rmii_clk_out = 0;
  365. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  366. MSCC_PHY_PAGE_EXT2);
  367. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
  368. /* Reg20E2 - Update RGMII RX_Clk Skews. */
  369. reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
  370. RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
  371. /* Reg20E2 - Update RGMII TX_Clk Skews. */
  372. reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
  373. RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
  374. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
  375. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
  376. /* Reg27E2 - Update Clk Slew Rate. */
  377. reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
  378. EDGE_RATE_CNTL_WIDTH, edge_rate);
  379. /* Reg27E2 - Update RMII Clk Out. */
  380. reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
  381. RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
  382. /* Update Reg27E2 */
  383. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
  384. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  385. MSCC_PHY_PAGE_STD);
  386. return genphy_config_aneg(phydev);
  387. }
  388. static struct phy_driver VSC8530_driver = {
  389. .name = "Microsemi VSC8530",
  390. .uid = PHY_ID_VSC8530,
  391. .mask = 0x000ffff0,
  392. .features = PHY_BASIC_FEATURES,
  393. .config = &vsc8531_config,
  394. .startup = &mscc_startup,
  395. .shutdown = &genphy_shutdown,
  396. };
  397. static struct phy_driver VSC8531_driver = {
  398. .name = "Microsemi VSC8531",
  399. .uid = PHY_ID_VSC8531,
  400. .mask = 0x000ffff0,
  401. .features = PHY_GBIT_FEATURES,
  402. .config = &vsc8531_config,
  403. .startup = &mscc_startup,
  404. .shutdown = &genphy_shutdown,
  405. };
  406. static struct phy_driver VSC8540_driver = {
  407. .name = "Microsemi VSC8540",
  408. .uid = PHY_ID_VSC8540,
  409. .mask = 0x000ffff0,
  410. .features = PHY_BASIC_FEATURES,
  411. .config = &vsc8541_config,
  412. .startup = &mscc_startup,
  413. .shutdown = &genphy_shutdown,
  414. };
  415. static struct phy_driver VSC8541_driver = {
  416. .name = "Microsemi VSC8541",
  417. .uid = PHY_ID_VSC8541,
  418. .mask = 0x000ffff0,
  419. .features = PHY_GBIT_FEATURES,
  420. .config = &vsc8541_config,
  421. .startup = &mscc_startup,
  422. .shutdown = &genphy_shutdown,
  423. };
  424. int phy_mscc_init(void)
  425. {
  426. phy_register(&VSC8530_driver);
  427. phy_register(&VSC8531_driver);
  428. phy_register(&VSC8540_driver);
  429. phy_register(&VSC8541_driver);
  430. return 0;
  431. }