]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/phy/mscc.c
net: hix5hd2_gmac: fix compatible strings name
[karo-tx-linux.git] / drivers / net / phy / mscc.c
1 /*
2  * Driver for Microsemi VSC85xx PHYs
3  *
4  * Author: Nagaraju Lakkaraju
5  * License: Dual MIT/GPL
6  * Copyright (c) 2016 Microsemi Corporation
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/mdio.h>
12 #include <linux/mii.h>
13 #include <linux/phy.h>
14 #include <linux/of.h>
15 #include <linux/netdevice.h>
16
17 enum rgmii_rx_clock_delay {
18         RGMII_RX_CLK_DELAY_0_2_NS = 0,
19         RGMII_RX_CLK_DELAY_0_8_NS = 1,
20         RGMII_RX_CLK_DELAY_1_1_NS = 2,
21         RGMII_RX_CLK_DELAY_1_7_NS = 3,
22         RGMII_RX_CLK_DELAY_2_0_NS = 4,
23         RGMII_RX_CLK_DELAY_2_3_NS = 5,
24         RGMII_RX_CLK_DELAY_2_6_NS = 6,
25         RGMII_RX_CLK_DELAY_3_4_NS = 7
26 };
27
28 /* Microsemi VSC85xx PHY registers */
29 /* IEEE 802. Std Registers */
30 #define MSCC_PHY_BYPASS_CONTROL           18
31 #define DISABLE_HP_AUTO_MDIX_MASK         0x0080
32 #define DISABLE_PAIR_SWAP_CORR_MASK       0x0020
33 #define DISABLE_POLARITY_CORR_MASK        0x0010
34
35 #define MSCC_PHY_EXT_PHY_CNTL_1           23
36 #define MAC_IF_SELECTION_MASK             0x1800
37 #define MAC_IF_SELECTION_GMII             0
38 #define MAC_IF_SELECTION_RMII             1
39 #define MAC_IF_SELECTION_RGMII            2
40 #define MAC_IF_SELECTION_POS              11
41 #define FAR_END_LOOPBACK_MODE_MASK        0x0008
42
43 #define MII_VSC85XX_INT_MASK              25
44 #define MII_VSC85XX_INT_MASK_MASK         0xa000
45 #define MII_VSC85XX_INT_MASK_WOL          0x0040
46 #define MII_VSC85XX_INT_STATUS            26
47
48 #define MSCC_PHY_WOL_MAC_CONTROL          27
49 #define EDGE_RATE_CNTL_POS                5
50 #define EDGE_RATE_CNTL_MASK               0x00E0
51
52 #define MSCC_PHY_DEV_AUX_CNTL             28
53 #define HP_AUTO_MDIX_X_OVER_IND_MASK      0x2000
54
55 #define MSCC_EXT_PAGE_ACCESS              31
56 #define MSCC_PHY_PAGE_STANDARD            0x0000 /* Standard registers */
57 #define MSCC_PHY_PAGE_EXTENDED            0x0001 /* Extended registers */
58 #define MSCC_PHY_PAGE_EXTENDED_2          0x0002 /* Extended reg - page 2 */
59
60 /* Extended Page 1 Registers */
61 #define MSCC_PHY_EXT_MODE_CNTL            19
62 #define FORCE_MDI_CROSSOVER_MASK          0x000C
63 #define FORCE_MDI_CROSSOVER_MDIX          0x000C
64 #define FORCE_MDI_CROSSOVER_MDI           0x0008
65
66 #define MSCC_PHY_ACTIPHY_CNTL             20
67 #define DOWNSHIFT_CNTL_MASK               0x001C
68 #define DOWNSHIFT_EN                      0x0010
69 #define DOWNSHIFT_CNTL_POS                2
70
71 /* Extended Page 2 Registers */
72 #define MSCC_PHY_RGMII_CNTL               20
73 #define RGMII_RX_CLK_DELAY_MASK           0x0070
74 #define RGMII_RX_CLK_DELAY_POS            4
75
76 #define MSCC_PHY_WOL_LOWER_MAC_ADDR       21
77 #define MSCC_PHY_WOL_MID_MAC_ADDR         22
78 #define MSCC_PHY_WOL_UPPER_MAC_ADDR       23
79 #define MSCC_PHY_WOL_LOWER_PASSWD         24
80 #define MSCC_PHY_WOL_MID_PASSWD           25
81 #define MSCC_PHY_WOL_UPPER_PASSWD         26
82
83 #define MSCC_PHY_WOL_MAC_CONTROL          27
84 #define SECURE_ON_ENABLE                  0x8000
85 #define SECURE_ON_PASSWD_LEN_4            0x4000
86
87 /* Microsemi PHY ID's */
88 #define PHY_ID_VSC8530                    0x00070560
89 #define PHY_ID_VSC8531                    0x00070570
90 #define PHY_ID_VSC8540                    0x00070760
91 #define PHY_ID_VSC8541                    0x00070770
92
93 #define MSCC_VDDMAC_1500                  1500
94 #define MSCC_VDDMAC_1800                  1800
95 #define MSCC_VDDMAC_2500                  2500
96 #define MSCC_VDDMAC_3300                  3300
97
98 #define DOWNSHIFT_COUNT_MAX               5
99
100 struct vsc8531_private {
101         int rate_magic;
102 };
103
104 #ifdef CONFIG_OF_MDIO
105 struct vsc8531_edge_rate_table {
106         u16 vddmac;
107         u8 slowdown[8];
108 };
109
110 static const struct vsc8531_edge_rate_table edge_table[] = {
111         {MSCC_VDDMAC_3300, { 0, 2,  4,  7, 10, 17, 29, 53} },
112         {MSCC_VDDMAC_2500, { 0, 3,  6, 10, 14, 23, 37, 63} },
113         {MSCC_VDDMAC_1800, { 0, 5,  9, 16, 23, 35, 52, 76} },
114         {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
115 };
116 #endif /* CONFIG_OF_MDIO */
117
118 static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
119 {
120         int rc;
121
122         rc = phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
123         return rc;
124 }
125
126 static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix)
127 {
128         u16 reg_val;
129
130         reg_val = phy_read(phydev, MSCC_PHY_DEV_AUX_CNTL);
131         if (reg_val & HP_AUTO_MDIX_X_OVER_IND_MASK)
132                 *mdix = ETH_TP_MDI_X;
133         else
134                 *mdix = ETH_TP_MDI;
135
136         return 0;
137 }
138
139 static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
140 {
141         int rc;
142         u16 reg_val;
143
144         reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL);
145         if ((mdix == ETH_TP_MDI) || (mdix == ETH_TP_MDI_X)) {
146                 reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK |
147                             DISABLE_POLARITY_CORR_MASK  |
148                             DISABLE_HP_AUTO_MDIX_MASK);
149         } else {
150                 reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK |
151                              DISABLE_POLARITY_CORR_MASK  |
152                              DISABLE_HP_AUTO_MDIX_MASK);
153         }
154         rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val);
155         if (rc != 0)
156                 return rc;
157
158         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
159         if (rc != 0)
160                 return rc;
161
162         reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL);
163         reg_val &= ~(FORCE_MDI_CROSSOVER_MASK);
164         if (mdix == ETH_TP_MDI)
165                 reg_val |= FORCE_MDI_CROSSOVER_MDI;
166         else if (mdix == ETH_TP_MDI_X)
167                 reg_val |= FORCE_MDI_CROSSOVER_MDIX;
168         rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val);
169         if (rc != 0)
170                 return rc;
171
172         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
173         if (rc != 0)
174                 return rc;
175
176         return genphy_restart_aneg(phydev);
177 }
178
179 static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
180 {
181         int rc;
182         u16 reg_val;
183
184         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
185         if (rc != 0)
186                 goto out;
187
188         reg_val = phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
189         reg_val &= DOWNSHIFT_CNTL_MASK;
190         if (!(reg_val & DOWNSHIFT_EN))
191                 *count = DOWNSHIFT_DEV_DISABLE;
192         else
193                 *count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
194         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
195
196 out:
197         return rc;
198 }
199
200 static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
201 {
202         int rc;
203         u16 reg_val;
204
205         if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
206                 /* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
207                 count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
208         } else if (count > DOWNSHIFT_COUNT_MAX || count == 1) {
209                 phydev_err(phydev, "Downshift count should be 2,3,4 or 5\n");
210                 return -ERANGE;
211         } else if (count) {
212                 /* Downshift count is either 2,3,4 or 5 */
213                 count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
214         }
215
216         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
217         if (rc != 0)
218                 goto out;
219
220         reg_val = phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
221         reg_val &= ~(DOWNSHIFT_CNTL_MASK);
222         reg_val |= count;
223         rc = phy_write(phydev, MSCC_PHY_ACTIPHY_CNTL, reg_val);
224         if (rc != 0)
225                 goto out;
226
227         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
228
229 out:
230         return rc;
231 }
232
233 static int vsc85xx_wol_set(struct phy_device *phydev,
234                            struct ethtool_wolinfo *wol)
235 {
236         int rc;
237         u16 reg_val;
238         u8  i;
239         u16 pwd[3] = {0, 0, 0};
240         struct ethtool_wolinfo *wol_conf = wol;
241         u8 *mac_addr = phydev->attached_dev->dev_addr;
242
243         mutex_lock(&phydev->lock);
244         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
245         if (rc != 0)
246                 goto out_unlock;
247
248         if (wol->wolopts & WAKE_MAGIC) {
249                 /* Store the device address for the magic packet */
250                 for (i = 0; i < ARRAY_SIZE(pwd); i++)
251                         pwd[i] = mac_addr[5 - (i * 2 + 1)] << 8 |
252                                  mac_addr[5 - i * 2];
253                 phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
254                 phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
255                 phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
256         } else {
257                 phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
258                 phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
259                 phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
260         }
261
262         if (wol_conf->wolopts & WAKE_MAGICSECURE) {
263                 for (i = 0; i < ARRAY_SIZE(pwd); i++)
264                         pwd[i] = wol_conf->sopass[5 - (i * 2 + 1)] << 8 |
265                                  wol_conf->sopass[5 - i * 2];
266                 phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
267                 phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
268                 phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
269         } else {
270                 phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
271                 phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
272                 phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
273         }
274
275         reg_val = phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
276         if (wol_conf->wolopts & WAKE_MAGICSECURE)
277                 reg_val |= SECURE_ON_ENABLE;
278         else
279                 reg_val &= ~SECURE_ON_ENABLE;
280         phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
281
282         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
283         if (rc != 0)
284                 goto out_unlock;
285
286         if (wol->wolopts & WAKE_MAGIC) {
287                 /* Enable the WOL interrupt */
288                 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
289                 reg_val |= MII_VSC85XX_INT_MASK_WOL;
290                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
291                 if (rc != 0)
292                         goto out_unlock;
293         } else {
294                 /* Disable the WOL interrupt */
295                 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
296                 reg_val &= (~MII_VSC85XX_INT_MASK_WOL);
297                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
298                 if (rc != 0)
299                         goto out_unlock;
300         }
301         /* Clear WOL iterrupt status */
302         reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS);
303
304 out_unlock:
305         mutex_unlock(&phydev->lock);
306
307         return rc;
308 }
309
310 static void vsc85xx_wol_get(struct phy_device *phydev,
311                             struct ethtool_wolinfo *wol)
312 {
313         int rc;
314         u16 reg_val;
315         u8  i;
316         u16 pwd[3] = {0, 0, 0};
317         struct ethtool_wolinfo *wol_conf = wol;
318
319         mutex_lock(&phydev->lock);
320         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
321         if (rc != 0)
322                 goto out_unlock;
323
324         reg_val = phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
325         if (reg_val & SECURE_ON_ENABLE)
326                 wol_conf->wolopts |= WAKE_MAGICSECURE;
327         if (wol_conf->wolopts & WAKE_MAGICSECURE) {
328                 pwd[0] = phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
329                 pwd[1] = phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
330                 pwd[2] = phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
331                 for (i = 0; i < ARRAY_SIZE(pwd); i++) {
332                         wol_conf->sopass[5 - i * 2] = pwd[i] & 0x00ff;
333                         wol_conf->sopass[5 - (i * 2 + 1)] = (pwd[i] & 0xff00)
334                                                             >> 8;
335                 }
336         }
337
338         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
339
340 out_unlock:
341         mutex_unlock(&phydev->lock);
342 }
343
344 #ifdef CONFIG_OF_MDIO
345 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
346 {
347         u8 sd;
348         u16 vdd;
349         int rc, i, j;
350         struct device *dev = &phydev->mdio.dev;
351         struct device_node *of_node = dev->of_node;
352         u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
353
354         if (!of_node)
355                 return -ENODEV;
356
357         rc = of_property_read_u16(of_node, "vsc8531,vddmac", &vdd);
358         if (rc != 0)
359                 vdd = MSCC_VDDMAC_3300;
360
361         rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", &sd);
362         if (rc != 0)
363                 sd = 0;
364
365         for (i = 0; i < ARRAY_SIZE(edge_table); i++)
366                 if (edge_table[i].vddmac == vdd)
367                         for (j = 0; j < sd_array_size; j++)
368                                 if (edge_table[i].slowdown[j] == sd)
369                                         return (sd_array_size - j - 1);
370
371         return -EINVAL;
372 }
373 #else
374 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
375 {
376         return 0;
377 }
378 #endif /* CONFIG_OF_MDIO */
379
380 static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
381 {
382         int rc;
383         u16 reg_val;
384
385         mutex_lock(&phydev->lock);
386         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
387         if (rc != 0)
388                 goto out_unlock;
389         reg_val = phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
390         reg_val &= ~(EDGE_RATE_CNTL_MASK);
391         reg_val |= (edge_rate << EDGE_RATE_CNTL_POS);
392         rc = phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
393         if (rc != 0)
394                 goto out_unlock;
395         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
396
397 out_unlock:
398         mutex_unlock(&phydev->lock);
399
400         return rc;
401 }
402
403 static int vsc85xx_mac_if_set(struct phy_device *phydev,
404                               phy_interface_t interface)
405 {
406         int rc;
407         u16 reg_val;
408
409         mutex_lock(&phydev->lock);
410         reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
411         reg_val &= ~(MAC_IF_SELECTION_MASK);
412         switch (interface) {
413         case PHY_INTERFACE_MODE_RGMII:
414                 reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS);
415                 break;
416         case PHY_INTERFACE_MODE_RMII:
417                 reg_val |= (MAC_IF_SELECTION_RMII << MAC_IF_SELECTION_POS);
418                 break;
419         case PHY_INTERFACE_MODE_MII:
420         case PHY_INTERFACE_MODE_GMII:
421                 reg_val |= (MAC_IF_SELECTION_GMII << MAC_IF_SELECTION_POS);
422                 break;
423         default:
424                 rc = -EINVAL;
425                 goto out_unlock;
426         }
427         rc = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, reg_val);
428         if (rc != 0)
429                 goto out_unlock;
430
431         rc = genphy_soft_reset(phydev);
432
433 out_unlock:
434         mutex_unlock(&phydev->lock);
435
436         return rc;
437 }
438
439 static int vsc85xx_default_config(struct phy_device *phydev)
440 {
441         int rc;
442         u16 reg_val;
443
444         phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
445         mutex_lock(&phydev->lock);
446         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
447         if (rc != 0)
448                 goto out_unlock;
449
450         reg_val = phy_read(phydev, MSCC_PHY_RGMII_CNTL);
451         reg_val &= ~(RGMII_RX_CLK_DELAY_MASK);
452         reg_val |= (RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS);
453         phy_write(phydev, MSCC_PHY_RGMII_CNTL, reg_val);
454         rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
455
456 out_unlock:
457         mutex_unlock(&phydev->lock);
458
459         return rc;
460 }
461
462 static int vsc85xx_get_tunable(struct phy_device *phydev,
463                                struct ethtool_tunable *tuna, void *data)
464 {
465         switch (tuna->id) {
466         case ETHTOOL_PHY_DOWNSHIFT:
467                 return vsc85xx_downshift_get(phydev, (u8 *)data);
468         default:
469                 return -EINVAL;
470         }
471 }
472
473 static int vsc85xx_set_tunable(struct phy_device *phydev,
474                                struct ethtool_tunable *tuna,
475                                const void *data)
476 {
477         switch (tuna->id) {
478         case ETHTOOL_PHY_DOWNSHIFT:
479                 return vsc85xx_downshift_set(phydev, *(u8 *)data);
480         default:
481                 return -EINVAL;
482         }
483 }
484
485 static int vsc85xx_config_init(struct phy_device *phydev)
486 {
487         int rc;
488         struct vsc8531_private *vsc8531 = phydev->priv;
489
490         rc = vsc85xx_default_config(phydev);
491         if (rc)
492                 return rc;
493
494         rc = vsc85xx_mac_if_set(phydev, phydev->interface);
495         if (rc)
496                 return rc;
497
498         rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
499         if (rc)
500                 return rc;
501
502         rc = genphy_config_init(phydev);
503
504         return rc;
505 }
506
507 static int vsc85xx_ack_interrupt(struct phy_device *phydev)
508 {
509         int rc = 0;
510
511         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
512                 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
513
514         return (rc < 0) ? rc : 0;
515 }
516
517 static int vsc85xx_config_intr(struct phy_device *phydev)
518 {
519         int rc;
520
521         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
522                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
523                                MII_VSC85XX_INT_MASK_MASK);
524         } else {
525                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, 0);
526                 if (rc < 0)
527                         return rc;
528                 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
529         }
530
531         return rc;
532 }
533
534 static int vsc85xx_config_aneg(struct phy_device *phydev)
535 {
536         int rc;
537
538         rc = vsc85xx_mdix_set(phydev, phydev->mdix_ctrl);
539         if (rc < 0)
540                 return rc;
541
542         return genphy_config_aneg(phydev);
543 }
544
545 static int vsc85xx_read_status(struct phy_device *phydev)
546 {
547         int rc;
548
549         rc = vsc85xx_mdix_get(phydev, &phydev->mdix);
550         if (rc < 0)
551                 return rc;
552
553         return genphy_read_status(phydev);
554 }
555
556 static int vsc85xx_probe(struct phy_device *phydev)
557 {
558         int rate_magic;
559         struct vsc8531_private *vsc8531;
560
561         rate_magic = vsc85xx_edge_rate_magic_get(phydev);
562         if (rate_magic < 0)
563                 return rate_magic;
564
565         vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
566         if (!vsc8531)
567                 return -ENOMEM;
568
569         phydev->priv = vsc8531;
570
571         vsc8531->rate_magic = rate_magic;
572
573         return 0;
574 }
575
576 /* Microsemi VSC85xx PHYs */
577 static struct phy_driver vsc85xx_driver[] = {
578 {
579         .phy_id         = PHY_ID_VSC8530,
580         .name           = "Microsemi FE VSC8530",
581         .phy_id_mask    = 0xfffffff0,
582         .features       = PHY_BASIC_FEATURES,
583         .flags          = PHY_HAS_INTERRUPT,
584         .soft_reset     = &genphy_soft_reset,
585         .config_init    = &vsc85xx_config_init,
586         .config_aneg    = &vsc85xx_config_aneg,
587         .aneg_done      = &genphy_aneg_done,
588         .read_status    = &vsc85xx_read_status,
589         .ack_interrupt  = &vsc85xx_ack_interrupt,
590         .config_intr    = &vsc85xx_config_intr,
591         .suspend        = &genphy_suspend,
592         .resume         = &genphy_resume,
593         .probe          = &vsc85xx_probe,
594         .set_wol        = &vsc85xx_wol_set,
595         .get_wol        = &vsc85xx_wol_get,
596         .get_tunable    = &vsc85xx_get_tunable,
597         .set_tunable    = &vsc85xx_set_tunable,
598 },
599 {
600         .phy_id         = PHY_ID_VSC8531,
601         .name           = "Microsemi VSC8531",
602         .phy_id_mask    = 0xfffffff0,
603         .features       = PHY_GBIT_FEATURES,
604         .flags          = PHY_HAS_INTERRUPT,
605         .soft_reset     = &genphy_soft_reset,
606         .config_init    = &vsc85xx_config_init,
607         .config_aneg    = &vsc85xx_config_aneg,
608         .aneg_done      = &genphy_aneg_done,
609         .read_status    = &vsc85xx_read_status,
610         .ack_interrupt  = &vsc85xx_ack_interrupt,
611         .config_intr    = &vsc85xx_config_intr,
612         .suspend        = &genphy_suspend,
613         .resume         = &genphy_resume,
614         .probe          = &vsc85xx_probe,
615         .set_wol        = &vsc85xx_wol_set,
616         .get_wol        = &vsc85xx_wol_get,
617         .get_tunable    = &vsc85xx_get_tunable,
618         .set_tunable    = &vsc85xx_set_tunable,
619 },
620 {
621         .phy_id         = PHY_ID_VSC8540,
622         .name           = "Microsemi FE VSC8540 SyncE",
623         .phy_id_mask    = 0xfffffff0,
624         .features       = PHY_BASIC_FEATURES,
625         .flags          = PHY_HAS_INTERRUPT,
626         .soft_reset     = &genphy_soft_reset,
627         .config_init    = &vsc85xx_config_init,
628         .config_aneg    = &vsc85xx_config_aneg,
629         .aneg_done      = &genphy_aneg_done,
630         .read_status    = &vsc85xx_read_status,
631         .ack_interrupt  = &vsc85xx_ack_interrupt,
632         .config_intr    = &vsc85xx_config_intr,
633         .suspend        = &genphy_suspend,
634         .resume         = &genphy_resume,
635         .probe          = &vsc85xx_probe,
636         .set_wol        = &vsc85xx_wol_set,
637         .get_wol        = &vsc85xx_wol_get,
638         .get_tunable    = &vsc85xx_get_tunable,
639         .set_tunable    = &vsc85xx_set_tunable,
640 },
641 {
642         .phy_id         = PHY_ID_VSC8541,
643         .name           = "Microsemi VSC8541 SyncE",
644         .phy_id_mask    = 0xfffffff0,
645         .features       = PHY_GBIT_FEATURES,
646         .flags          = PHY_HAS_INTERRUPT,
647         .soft_reset     = &genphy_soft_reset,
648         .config_init    = &vsc85xx_config_init,
649         .config_aneg    = &vsc85xx_config_aneg,
650         .aneg_done      = &genphy_aneg_done,
651         .read_status    = &vsc85xx_read_status,
652         .ack_interrupt  = &vsc85xx_ack_interrupt,
653         .config_intr    = &vsc85xx_config_intr,
654         .suspend        = &genphy_suspend,
655         .resume         = &genphy_resume,
656         .probe          = &vsc85xx_probe,
657         .set_wol        = &vsc85xx_wol_set,
658         .get_wol        = &vsc85xx_wol_get,
659         .get_tunable    = &vsc85xx_get_tunable,
660         .set_tunable    = &vsc85xx_set_tunable,
661 }
662
663 };
664
665 module_phy_driver(vsc85xx_driver);
666
667 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
668         { PHY_ID_VSC8530, 0xfffffff0, },
669         { PHY_ID_VSC8531, 0xfffffff0, },
670         { PHY_ID_VSC8540, 0xfffffff0, },
671         { PHY_ID_VSC8541, 0xfffffff0, },
672         { }
673 };
674
675 MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
676
677 MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
678 MODULE_AUTHOR("Nagaraju Lakkaraju");
679 MODULE_LICENSE("Dual MIT/GPL");