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