6f102f134edb7e95c60f4b1e8a886c1b8e11b7d1
[oweals/u-boot.git] / drivers / net / phy / mscc.c
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 }