blob: 439f5e3c5cf696181370ff1a3bc99959d372cf80 [file] [log] [blame]
John Haechtenee253f92016-12-09 22:15:17 +00001/*
2 * Microsemi PHY drivers
3 *
4 * SPDX-License-Identifier: The MIT License (MIT)
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
125vsc_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
137static 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
199static 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
232static 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
244static 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
273static 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
340static 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
400static 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
460static 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
470static 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
480static 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
490static 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
500int 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}