Merge branch 'net-phy-mscc-various-improvements-to-Microsemi-PHY-driver'
[linux-2.6-microblaze.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 #include <dt-bindings/net/mscc-phy-vsc8531.h>
17
18 enum rgmii_rx_clock_delay {
19         RGMII_RX_CLK_DELAY_0_2_NS = 0,
20         RGMII_RX_CLK_DELAY_0_8_NS = 1,
21         RGMII_RX_CLK_DELAY_1_1_NS = 2,
22         RGMII_RX_CLK_DELAY_1_7_NS = 3,
23         RGMII_RX_CLK_DELAY_2_0_NS = 4,
24         RGMII_RX_CLK_DELAY_2_3_NS = 5,
25         RGMII_RX_CLK_DELAY_2_6_NS = 6,
26         RGMII_RX_CLK_DELAY_3_4_NS = 7
27 };
28
29 /* Microsemi VSC85xx PHY registers */
30 /* IEEE 802. Std Registers */
31 #define MSCC_PHY_BYPASS_CONTROL           18
32 #define DISABLE_HP_AUTO_MDIX_MASK         0x0080
33 #define DISABLE_PAIR_SWAP_CORR_MASK       0x0020
34 #define DISABLE_POLARITY_CORR_MASK        0x0010
35
36 #define MSCC_PHY_ERR_RX_CNT               19
37 #define MSCC_PHY_ERR_FALSE_CARRIER_CNT    20
38 #define MSCC_PHY_ERR_LINK_DISCONNECT_CNT  21
39 #define ERR_CNT_MASK                      GENMASK(7, 0)
40
41 #define MSCC_PHY_EXT_PHY_CNTL_1           23
42 #define MAC_IF_SELECTION_MASK             0x1800
43 #define MAC_IF_SELECTION_GMII             0
44 #define MAC_IF_SELECTION_RMII             1
45 #define MAC_IF_SELECTION_RGMII            2
46 #define MAC_IF_SELECTION_POS              11
47 #define FAR_END_LOOPBACK_MODE_MASK        0x0008
48
49 #define MII_VSC85XX_INT_MASK              25
50 #define MII_VSC85XX_INT_MASK_MASK         0xa000
51 #define MII_VSC85XX_INT_MASK_WOL          0x0040
52 #define MII_VSC85XX_INT_STATUS            26
53
54 #define MSCC_PHY_WOL_MAC_CONTROL          27
55 #define EDGE_RATE_CNTL_POS                5
56 #define EDGE_RATE_CNTL_MASK               0x00E0
57
58 #define MSCC_PHY_DEV_AUX_CNTL             28
59 #define HP_AUTO_MDIX_X_OVER_IND_MASK      0x2000
60
61 #define MSCC_PHY_LED_MODE_SEL             29
62 #define LED_MODE_SEL_POS(x)               ((x) * 4)
63 #define LED_MODE_SEL_MASK(x)              (GENMASK(3, 0) << LED_MODE_SEL_POS(x))
64 #define LED_MODE_SEL(x, mode)             (((mode) << LED_MODE_SEL_POS(x)) & LED_MODE_SEL_MASK(x))
65
66 #define MSCC_EXT_PAGE_ACCESS              31
67 #define MSCC_PHY_PAGE_STANDARD            0x0000 /* Standard registers */
68 #define MSCC_PHY_PAGE_EXTENDED            0x0001 /* Extended registers */
69 #define MSCC_PHY_PAGE_EXTENDED_2          0x0002 /* Extended reg - page 2 */
70 #define MSCC_PHY_PAGE_TR                  0x52b5 /* Token ring registers */
71
72 /* Extended Page 1 Registers */
73 #define MSCC_PHY_CU_MEDIA_CRC_VALID_CNT   18
74 #define VALID_CRC_CNT_CRC_MASK            GENMASK(13, 0)
75
76 #define MSCC_PHY_EXT_MODE_CNTL            19
77 #define FORCE_MDI_CROSSOVER_MASK          0x000C
78 #define FORCE_MDI_CROSSOVER_MDIX          0x000C
79 #define FORCE_MDI_CROSSOVER_MDI           0x0008
80
81 #define MSCC_PHY_ACTIPHY_CNTL             20
82 #define DOWNSHIFT_CNTL_MASK               0x001C
83 #define DOWNSHIFT_EN                      0x0010
84 #define DOWNSHIFT_CNTL_POS                2
85
86 #define MSCC_PHY_EXT_PHY_CNTL_4           23
87
88 /* Extended Page 2 Registers */
89 #define MSCC_PHY_RGMII_CNTL               20
90 #define RGMII_RX_CLK_DELAY_MASK           0x0070
91 #define RGMII_RX_CLK_DELAY_POS            4
92
93 #define MSCC_PHY_WOL_LOWER_MAC_ADDR       21
94 #define MSCC_PHY_WOL_MID_MAC_ADDR         22
95 #define MSCC_PHY_WOL_UPPER_MAC_ADDR       23
96 #define MSCC_PHY_WOL_LOWER_PASSWD         24
97 #define MSCC_PHY_WOL_MID_PASSWD           25
98 #define MSCC_PHY_WOL_UPPER_PASSWD         26
99
100 #define MSCC_PHY_WOL_MAC_CONTROL          27
101 #define SECURE_ON_ENABLE                  0x8000
102 #define SECURE_ON_PASSWD_LEN_4            0x4000
103
104 /* Token ring page Registers */
105 #define MSCC_PHY_TR_CNTL                  16
106 #define TR_WRITE                          0x8000
107 #define TR_ADDR(x)                        (0x7fff & (x))
108 #define MSCC_PHY_TR_LSB                   17
109 #define MSCC_PHY_TR_MSB                   18
110
111 /* Microsemi PHY ID's */
112 #define PHY_ID_VSC8530                    0x00070560
113 #define PHY_ID_VSC8531                    0x00070570
114 #define PHY_ID_VSC8540                    0x00070760
115 #define PHY_ID_VSC8541                    0x00070770
116
117 #define MSCC_VDDMAC_1500                  1500
118 #define MSCC_VDDMAC_1800                  1800
119 #define MSCC_VDDMAC_2500                  2500
120 #define MSCC_VDDMAC_3300                  3300
121
122 #define DOWNSHIFT_COUNT_MAX               5
123
124 #define MAX_LEDS                          4
125 #define VSC85XX_SUPP_LED_MODES (BIT(VSC8531_LINK_ACTIVITY) | \
126                                 BIT(VSC8531_LINK_1000_ACTIVITY) | \
127                                 BIT(VSC8531_LINK_100_ACTIVITY) | \
128                                 BIT(VSC8531_LINK_10_ACTIVITY) | \
129                                 BIT(VSC8531_LINK_100_1000_ACTIVITY) | \
130                                 BIT(VSC8531_LINK_10_1000_ACTIVITY) | \
131                                 BIT(VSC8531_LINK_10_100_ACTIVITY) | \
132                                 BIT(VSC8531_DUPLEX_COLLISION) | \
133                                 BIT(VSC8531_COLLISION) | \
134                                 BIT(VSC8531_ACTIVITY) | \
135                                 BIT(VSC8531_AUTONEG_FAULT) | \
136                                 BIT(VSC8531_SERIAL_MODE) | \
137                                 BIT(VSC8531_FORCE_LED_OFF) | \
138                                 BIT(VSC8531_FORCE_LED_ON))
139
140 struct reg_val {
141         u16     reg;
142         u32     val;
143 };
144
145 struct vsc85xx_hw_stat {
146         const char *string;
147         u8 reg;
148         u16 page;
149         u16 mask;
150 };
151
152 static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] = {
153         {
154                 .string = "phy_receive_errors",
155                 .reg    = MSCC_PHY_ERR_RX_CNT,
156                 .page   = MSCC_PHY_PAGE_STANDARD,
157                 .mask   = ERR_CNT_MASK,
158         }, {
159                 .string = "phy_false_carrier",
160                 .reg    = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
161                 .page   = MSCC_PHY_PAGE_STANDARD,
162                 .mask   = ERR_CNT_MASK,
163         }, {
164                 .string = "phy_cu_media_link_disconnect",
165                 .reg    = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
166                 .page   = MSCC_PHY_PAGE_STANDARD,
167                 .mask   = ERR_CNT_MASK,
168         }, {
169                 .string = "phy_cu_media_crc_good_count",
170                 .reg    = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
171                 .page   = MSCC_PHY_PAGE_EXTENDED,
172                 .mask   = VALID_CRC_CNT_CRC_MASK,
173         }, {
174                 .string = "phy_cu_media_crc_error_count",
175                 .reg    = MSCC_PHY_EXT_PHY_CNTL_4,
176                 .page   = MSCC_PHY_PAGE_EXTENDED,
177                 .mask   = ERR_CNT_MASK,
178         },
179 };
180
181 struct vsc8531_private {
182         int rate_magic;
183         u16 supp_led_modes;
184         u32 leds_mode[MAX_LEDS];
185         u8 nleds;
186         const struct vsc85xx_hw_stat *hw_stats;
187         u64 *stats;
188         int nstats;
189 };
190
191 #ifdef CONFIG_OF_MDIO
192 struct vsc8531_edge_rate_table {
193         u32 vddmac;
194         u32 slowdown[8];
195 };
196
197 static const struct vsc8531_edge_rate_table edge_table[] = {
198         {MSCC_VDDMAC_3300, { 0, 2,  4,  7, 10, 17, 29, 53} },
199         {MSCC_VDDMAC_2500, { 0, 3,  6, 10, 14, 23, 37, 63} },
200         {MSCC_VDDMAC_1800, { 0, 5,  9, 16, 23, 35, 52, 76} },
201         {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
202 };
203 #endif /* CONFIG_OF_MDIO */
204
205 static int vsc85xx_phy_read_page(struct phy_device *phydev)
206 {
207         return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
208 }
209
210 static int vsc85xx_phy_write_page(struct phy_device *phydev, int page)
211 {
212         return __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
213 }
214
215 static int vsc85xx_get_sset_count(struct phy_device *phydev)
216 {
217         struct vsc8531_private *priv = phydev->priv;
218
219         if (!priv)
220                 return 0;
221
222         return priv->nstats;
223 }
224
225 static void vsc85xx_get_strings(struct phy_device *phydev, u8 *data)
226 {
227         struct vsc8531_private *priv = phydev->priv;
228         int i;
229
230         if (!priv)
231                 return;
232
233         for (i = 0; i < priv->nstats; i++)
234                 strlcpy(data + i * ETH_GSTRING_LEN, priv->hw_stats[i].string,
235                         ETH_GSTRING_LEN);
236 }
237
238 static u64 vsc85xx_get_stat(struct phy_device *phydev, int i)
239 {
240         struct vsc8531_private *priv = phydev->priv;
241         int val;
242
243         val = phy_read_paged(phydev, priv->hw_stats[i].page,
244                              priv->hw_stats[i].reg);
245         if (val < 0)
246                 return U64_MAX;
247
248         val = val & priv->hw_stats[i].mask;
249         priv->stats[i] += val;
250
251         return priv->stats[i];
252 }
253
254 static void vsc85xx_get_stats(struct phy_device *phydev,
255                               struct ethtool_stats *stats, u64 *data)
256 {
257         struct vsc8531_private *priv = phydev->priv;
258         int i;
259
260         if (!priv)
261                 return;
262
263         for (i = 0; i < priv->nstats; i++)
264                 data[i] = vsc85xx_get_stat(phydev, i);
265 }
266
267 static int vsc85xx_led_cntl_set(struct phy_device *phydev,
268                                 u8 led_num,
269                                 u8 mode)
270 {
271         int rc;
272         u16 reg_val;
273
274         mutex_lock(&phydev->lock);
275         reg_val = phy_read(phydev, MSCC_PHY_LED_MODE_SEL);
276         reg_val &= ~LED_MODE_SEL_MASK(led_num);
277         reg_val |= LED_MODE_SEL(led_num, (u16)mode);
278         rc = phy_write(phydev, MSCC_PHY_LED_MODE_SEL, reg_val);
279         mutex_unlock(&phydev->lock);
280
281         return rc;
282 }
283
284 static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix)
285 {
286         u16 reg_val;
287
288         reg_val = phy_read(phydev, MSCC_PHY_DEV_AUX_CNTL);
289         if (reg_val & HP_AUTO_MDIX_X_OVER_IND_MASK)
290                 *mdix = ETH_TP_MDI_X;
291         else
292                 *mdix = ETH_TP_MDI;
293
294         return 0;
295 }
296
297 static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
298 {
299         int rc;
300         u16 reg_val;
301
302         reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL);
303         if (mdix == ETH_TP_MDI || mdix == ETH_TP_MDI_X) {
304                 reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK |
305                             DISABLE_POLARITY_CORR_MASK  |
306                             DISABLE_HP_AUTO_MDIX_MASK);
307         } else {
308                 reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK |
309                              DISABLE_POLARITY_CORR_MASK  |
310                              DISABLE_HP_AUTO_MDIX_MASK);
311         }
312         rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val);
313         if (rc)
314                 return rc;
315
316         reg_val = 0;
317
318         if (mdix == ETH_TP_MDI)
319                 reg_val = FORCE_MDI_CROSSOVER_MDI;
320         else if (mdix == ETH_TP_MDI_X)
321                 reg_val = FORCE_MDI_CROSSOVER_MDIX;
322
323         rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
324                               MSCC_PHY_EXT_MODE_CNTL, FORCE_MDI_CROSSOVER_MASK,
325                               reg_val);
326         if (rc < 0)
327                 return rc;
328
329         return genphy_restart_aneg(phydev);
330 }
331
332 static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
333 {
334         u16 reg_val;
335
336         reg_val = phy_read_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
337                                  MSCC_PHY_ACTIPHY_CNTL);
338         if (reg_val < 0)
339                 return reg_val;
340
341         reg_val &= DOWNSHIFT_CNTL_MASK;
342         if (!(reg_val & DOWNSHIFT_EN))
343                 *count = DOWNSHIFT_DEV_DISABLE;
344         else
345                 *count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
346
347         return 0;
348 }
349
350 static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
351 {
352         if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
353                 /* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
354                 count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
355         } else if (count > DOWNSHIFT_COUNT_MAX || count == 1) {
356                 phydev_err(phydev, "Downshift count should be 2,3,4 or 5\n");
357                 return -ERANGE;
358         } else if (count) {
359                 /* Downshift count is either 2,3,4 or 5 */
360                 count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
361         }
362
363         return phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
364                                 MSCC_PHY_ACTIPHY_CNTL, DOWNSHIFT_CNTL_MASK,
365                                 count);
366 }
367
368 static int vsc85xx_wol_set(struct phy_device *phydev,
369                            struct ethtool_wolinfo *wol)
370 {
371         int rc;
372         u16 reg_val;
373         u8  i;
374         u16 pwd[3] = {0, 0, 0};
375         struct ethtool_wolinfo *wol_conf = wol;
376         u8 *mac_addr = phydev->attached_dev->dev_addr;
377
378         mutex_lock(&phydev->lock);
379         rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
380         if (rc < 0) {
381                 rc = phy_restore_page(phydev, rc, rc);
382                 goto out_unlock;
383         }
384
385         if (wol->wolopts & WAKE_MAGIC) {
386                 /* Store the device address for the magic packet */
387                 for (i = 0; i < ARRAY_SIZE(pwd); i++)
388                         pwd[i] = mac_addr[5 - (i * 2 + 1)] << 8 |
389                                  mac_addr[5 - i * 2];
390                 __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
391                 __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
392                 __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
393         } else {
394                 __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
395                 __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
396                 __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
397         }
398
399         if (wol_conf->wolopts & WAKE_MAGICSECURE) {
400                 for (i = 0; i < ARRAY_SIZE(pwd); i++)
401                         pwd[i] = wol_conf->sopass[5 - (i * 2 + 1)] << 8 |
402                                  wol_conf->sopass[5 - i * 2];
403                 __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
404                 __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
405                 __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
406         } else {
407                 __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
408                 __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
409                 __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
410         }
411
412         reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
413         if (wol_conf->wolopts & WAKE_MAGICSECURE)
414                 reg_val |= SECURE_ON_ENABLE;
415         else
416                 reg_val &= ~SECURE_ON_ENABLE;
417         __phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
418
419         rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
420         if (rc < 0)
421                 goto out_unlock;
422
423         if (wol->wolopts & WAKE_MAGIC) {
424                 /* Enable the WOL interrupt */
425                 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
426                 reg_val |= MII_VSC85XX_INT_MASK_WOL;
427                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
428                 if (rc)
429                         goto out_unlock;
430         } else {
431                 /* Disable the WOL interrupt */
432                 reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
433                 reg_val &= (~MII_VSC85XX_INT_MASK_WOL);
434                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
435                 if (rc)
436                         goto out_unlock;
437         }
438         /* Clear WOL iterrupt status */
439         reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS);
440
441 out_unlock:
442         mutex_unlock(&phydev->lock);
443
444         return rc;
445 }
446
447 static void vsc85xx_wol_get(struct phy_device *phydev,
448                             struct ethtool_wolinfo *wol)
449 {
450         int rc;
451         u16 reg_val;
452         u8  i;
453         u16 pwd[3] = {0, 0, 0};
454         struct ethtool_wolinfo *wol_conf = wol;
455
456         mutex_lock(&phydev->lock);
457         rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
458         if (rc < 0)
459                 goto out_unlock;
460
461         reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
462         if (reg_val & SECURE_ON_ENABLE)
463                 wol_conf->wolopts |= WAKE_MAGICSECURE;
464         if (wol_conf->wolopts & WAKE_MAGICSECURE) {
465                 pwd[0] = __phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
466                 pwd[1] = __phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
467                 pwd[2] = __phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
468                 for (i = 0; i < ARRAY_SIZE(pwd); i++) {
469                         wol_conf->sopass[5 - i * 2] = pwd[i] & 0x00ff;
470                         wol_conf->sopass[5 - (i * 2 + 1)] = (pwd[i] & 0xff00)
471                                                             >> 8;
472                 }
473         }
474
475 out_unlock:
476         phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
477         mutex_unlock(&phydev->lock);
478 }
479
480 #ifdef CONFIG_OF_MDIO
481 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
482 {
483         u32 vdd, sd;
484         int i, j;
485         struct device *dev = &phydev->mdio.dev;
486         struct device_node *of_node = dev->of_node;
487         u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
488
489         if (!of_node)
490                 return -ENODEV;
491
492         if (of_property_read_u32(of_node, "vsc8531,vddmac", &vdd))
493                 vdd = MSCC_VDDMAC_3300;
494
495         if (of_property_read_u32(of_node, "vsc8531,edge-slowdown", &sd))
496                 sd = 0;
497
498         for (i = 0; i < ARRAY_SIZE(edge_table); i++)
499                 if (edge_table[i].vddmac == vdd)
500                         for (j = 0; j < sd_array_size; j++)
501                                 if (edge_table[i].slowdown[j] == sd)
502                                         return (sd_array_size - j - 1);
503
504         return -EINVAL;
505 }
506
507 static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
508                                    char *led,
509                                    u32 default_mode)
510 {
511         struct vsc8531_private *priv = phydev->priv;
512         struct device *dev = &phydev->mdio.dev;
513         struct device_node *of_node = dev->of_node;
514         u32 led_mode;
515         int err;
516
517         if (!of_node)
518                 return -ENODEV;
519
520         led_mode = default_mode;
521         err = of_property_read_u32(of_node, led, &led_mode);
522         if (!err && !(BIT(led_mode) & priv->supp_led_modes)) {
523                 phydev_err(phydev, "DT %s invalid\n", led);
524                 return -EINVAL;
525         }
526
527         return led_mode;
528 }
529
530 #else
531 static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
532 {
533         return 0;
534 }
535
536 static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
537                                    char *led,
538                                    u8 default_mode)
539 {
540         return default_mode;
541 }
542 #endif /* CONFIG_OF_MDIO */
543
544 static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
545                                     u32 *default_mode)
546 {
547         struct vsc8531_private *priv = phydev->priv;
548         char led_dt_prop[28];
549         int i, ret;
550
551         for (i = 0; i < priv->nleds; i++) {
552                 ret = sprintf(led_dt_prop, "vsc8531,led-%d-mode", i);
553                 if (ret < 0)
554                         return ret;
555
556                 ret = vsc85xx_dt_led_mode_get(phydev, led_dt_prop,
557                                               default_mode[i]);
558                 if (ret < 0)
559                         return ret;
560                 priv->leds_mode[i] = ret;
561         }
562
563         return 0;
564 }
565
566 static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
567 {
568         int rc;
569
570         mutex_lock(&phydev->lock);
571         rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
572                               MSCC_PHY_WOL_MAC_CONTROL, EDGE_RATE_CNTL_MASK,
573                               edge_rate << EDGE_RATE_CNTL_POS);
574         mutex_unlock(&phydev->lock);
575
576         return rc;
577 }
578
579 static int vsc85xx_mac_if_set(struct phy_device *phydev,
580                               phy_interface_t interface)
581 {
582         int rc;
583         u16 reg_val;
584
585         mutex_lock(&phydev->lock);
586         reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
587         reg_val &= ~(MAC_IF_SELECTION_MASK);
588         switch (interface) {
589         case PHY_INTERFACE_MODE_RGMII:
590                 reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS);
591                 break;
592         case PHY_INTERFACE_MODE_RMII:
593                 reg_val |= (MAC_IF_SELECTION_RMII << MAC_IF_SELECTION_POS);
594                 break;
595         case PHY_INTERFACE_MODE_MII:
596         case PHY_INTERFACE_MODE_GMII:
597                 reg_val |= (MAC_IF_SELECTION_GMII << MAC_IF_SELECTION_POS);
598                 break;
599         default:
600                 rc = -EINVAL;
601                 goto out_unlock;
602         }
603         rc = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, reg_val);
604         if (rc)
605                 goto out_unlock;
606
607         rc = genphy_soft_reset(phydev);
608
609 out_unlock:
610         mutex_unlock(&phydev->lock);
611
612         return rc;
613 }
614
615 static int vsc85xx_default_config(struct phy_device *phydev)
616 {
617         int rc;
618         u16 reg_val;
619
620         phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
621         mutex_lock(&phydev->lock);
622         rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
623         if (rc < 0)
624                 goto out_unlock;
625
626         reg_val = phy_read(phydev, MSCC_PHY_RGMII_CNTL);
627         reg_val &= ~(RGMII_RX_CLK_DELAY_MASK);
628         reg_val |= (RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS);
629         phy_write(phydev, MSCC_PHY_RGMII_CNTL, reg_val);
630
631 out_unlock:
632         rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
633         mutex_unlock(&phydev->lock);
634
635         return rc;
636 }
637
638 static int vsc85xx_get_tunable(struct phy_device *phydev,
639                                struct ethtool_tunable *tuna, void *data)
640 {
641         switch (tuna->id) {
642         case ETHTOOL_PHY_DOWNSHIFT:
643                 return vsc85xx_downshift_get(phydev, (u8 *)data);
644         default:
645                 return -EINVAL;
646         }
647 }
648
649 static int vsc85xx_set_tunable(struct phy_device *phydev,
650                                struct ethtool_tunable *tuna,
651                                const void *data)
652 {
653         switch (tuna->id) {
654         case ETHTOOL_PHY_DOWNSHIFT:
655                 return vsc85xx_downshift_set(phydev, *(u8 *)data);
656         default:
657                 return -EINVAL;
658         }
659 }
660
661 /* mdiobus lock should be locked when using this function */
662 static void vsc85xx_tr_write(struct phy_device *phydev, u16 addr, u32 val)
663 {
664         __phy_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
665         __phy_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
666         __phy_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
667 }
668
669 static int vsc85xx_eee_init_seq_set(struct phy_device *phydev)
670 {
671         const struct reg_val init_eee[] = {
672                 {0x0f82, 0x0012b00a},
673                 {0x1686, 0x00000004},
674                 {0x168c, 0x00d2c46f},
675                 {0x17a2, 0x00000620},
676                 {0x16a0, 0x00eeffdd},
677                 {0x16a6, 0x00071448},
678                 {0x16a4, 0x0013132f},
679                 {0x16a8, 0x00000000},
680                 {0x0ffc, 0x00c0a028},
681                 {0x0fe8, 0x0091b06c},
682                 {0x0fea, 0x00041600},
683                 {0x0f80, 0x00000af4},
684                 {0x0fec, 0x00901809},
685                 {0x0fee, 0x0000a6a1},
686                 {0x0ffe, 0x00b01007},
687                 {0x16b0, 0x00eeff00},
688                 {0x16b2, 0x00007000},
689                 {0x16b4, 0x00000814},
690         };
691         unsigned int i;
692         int oldpage;
693
694         mutex_lock(&phydev->lock);
695         oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
696         if (oldpage < 0)
697                 goto out_unlock;
698
699         for (i = 0; i < ARRAY_SIZE(init_eee); i++)
700                 vsc85xx_tr_write(phydev, init_eee[i].reg, init_eee[i].val);
701
702 out_unlock:
703         oldpage = phy_restore_page(phydev, oldpage, oldpage);
704         mutex_unlock(&phydev->lock);
705
706         return oldpage;
707 }
708
709 static int vsc85xx_config_init(struct phy_device *phydev)
710 {
711         int rc, i;
712         struct vsc8531_private *vsc8531 = phydev->priv;
713
714         rc = vsc85xx_default_config(phydev);
715         if (rc)
716                 return rc;
717
718         rc = vsc85xx_mac_if_set(phydev, phydev->interface);
719         if (rc)
720                 return rc;
721
722         rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
723         if (rc)
724                 return rc;
725
726         rc = vsc85xx_eee_init_seq_set(phydev);
727         if (rc)
728                 return rc;
729
730         for (i = 0; i < vsc8531->nleds; i++) {
731                 rc = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
732                 if (rc)
733                         return rc;
734         }
735
736         return genphy_config_init(phydev);
737 }
738
739 static int vsc85xx_ack_interrupt(struct phy_device *phydev)
740 {
741         int rc = 0;
742
743         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
744                 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
745
746         return (rc < 0) ? rc : 0;
747 }
748
749 static int vsc85xx_config_intr(struct phy_device *phydev)
750 {
751         int rc;
752
753         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
754                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
755                                MII_VSC85XX_INT_MASK_MASK);
756         } else {
757                 rc = phy_write(phydev, MII_VSC85XX_INT_MASK, 0);
758                 if (rc < 0)
759                         return rc;
760                 rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
761         }
762
763         return rc;
764 }
765
766 static int vsc85xx_config_aneg(struct phy_device *phydev)
767 {
768         int rc;
769
770         rc = vsc85xx_mdix_set(phydev, phydev->mdix_ctrl);
771         if (rc < 0)
772                 return rc;
773
774         return genphy_config_aneg(phydev);
775 }
776
777 static int vsc85xx_read_status(struct phy_device *phydev)
778 {
779         int rc;
780
781         rc = vsc85xx_mdix_get(phydev, &phydev->mdix);
782         if (rc < 0)
783                 return rc;
784
785         return genphy_read_status(phydev);
786 }
787
788 static int vsc85xx_probe(struct phy_device *phydev)
789 {
790         struct vsc8531_private *vsc8531;
791         int rate_magic;
792         u32 default_mode[2] = {VSC8531_LINK_1000_ACTIVITY,
793            VSC8531_LINK_100_ACTIVITY};
794
795         rate_magic = vsc85xx_edge_rate_magic_get(phydev);
796         if (rate_magic < 0)
797                 return rate_magic;
798
799         vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
800         if (!vsc8531)
801                 return -ENOMEM;
802
803         phydev->priv = vsc8531;
804
805         vsc8531->rate_magic = rate_magic;
806         vsc8531->nleds = 2;
807         vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
808         vsc8531->hw_stats = vsc85xx_hw_stats;
809         vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
810         vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
811                                             sizeof(u64), GFP_KERNEL);
812         if (!vsc8531->stats)
813                 return -ENOMEM;
814
815         return vsc85xx_dt_led_modes_get(phydev, default_mode);
816 }
817
818 /* Microsemi VSC85xx PHYs */
819 static struct phy_driver vsc85xx_driver[] = {
820 {
821         .phy_id         = PHY_ID_VSC8530,
822         .name           = "Microsemi FE VSC8530",
823         .phy_id_mask    = 0xfffffff0,
824         .features       = PHY_BASIC_FEATURES,
825         .flags          = PHY_HAS_INTERRUPT,
826         .soft_reset     = &genphy_soft_reset,
827         .config_init    = &vsc85xx_config_init,
828         .config_aneg    = &vsc85xx_config_aneg,
829         .aneg_done      = &genphy_aneg_done,
830         .read_status    = &vsc85xx_read_status,
831         .ack_interrupt  = &vsc85xx_ack_interrupt,
832         .config_intr    = &vsc85xx_config_intr,
833         .suspend        = &genphy_suspend,
834         .resume         = &genphy_resume,
835         .probe          = &vsc85xx_probe,
836         .set_wol        = &vsc85xx_wol_set,
837         .get_wol        = &vsc85xx_wol_get,
838         .get_tunable    = &vsc85xx_get_tunable,
839         .set_tunable    = &vsc85xx_set_tunable,
840         .read_page      = &vsc85xx_phy_read_page,
841         .write_page     = &vsc85xx_phy_write_page,
842         .get_sset_count = &vsc85xx_get_sset_count,
843         .get_strings    = &vsc85xx_get_strings,
844         .get_stats      = &vsc85xx_get_stats,
845 },
846 {
847         .phy_id         = PHY_ID_VSC8531,
848         .name           = "Microsemi VSC8531",
849         .phy_id_mask    = 0xfffffff0,
850         .features       = PHY_GBIT_FEATURES,
851         .flags          = PHY_HAS_INTERRUPT,
852         .soft_reset     = &genphy_soft_reset,
853         .config_init    = &vsc85xx_config_init,
854         .config_aneg    = &vsc85xx_config_aneg,
855         .aneg_done      = &genphy_aneg_done,
856         .read_status    = &vsc85xx_read_status,
857         .ack_interrupt  = &vsc85xx_ack_interrupt,
858         .config_intr    = &vsc85xx_config_intr,
859         .suspend        = &genphy_suspend,
860         .resume         = &genphy_resume,
861         .probe          = &vsc85xx_probe,
862         .set_wol        = &vsc85xx_wol_set,
863         .get_wol        = &vsc85xx_wol_get,
864         .get_tunable    = &vsc85xx_get_tunable,
865         .set_tunable    = &vsc85xx_set_tunable,
866         .read_page      = &vsc85xx_phy_read_page,
867         .write_page     = &vsc85xx_phy_write_page,
868         .get_sset_count = &vsc85xx_get_sset_count,
869         .get_strings    = &vsc85xx_get_strings,
870         .get_stats      = &vsc85xx_get_stats,
871 },
872 {
873         .phy_id         = PHY_ID_VSC8540,
874         .name           = "Microsemi FE VSC8540 SyncE",
875         .phy_id_mask    = 0xfffffff0,
876         .features       = PHY_BASIC_FEATURES,
877         .flags          = PHY_HAS_INTERRUPT,
878         .soft_reset     = &genphy_soft_reset,
879         .config_init    = &vsc85xx_config_init,
880         .config_aneg    = &vsc85xx_config_aneg,
881         .aneg_done      = &genphy_aneg_done,
882         .read_status    = &vsc85xx_read_status,
883         .ack_interrupt  = &vsc85xx_ack_interrupt,
884         .config_intr    = &vsc85xx_config_intr,
885         .suspend        = &genphy_suspend,
886         .resume         = &genphy_resume,
887         .probe          = &vsc85xx_probe,
888         .set_wol        = &vsc85xx_wol_set,
889         .get_wol        = &vsc85xx_wol_get,
890         .get_tunable    = &vsc85xx_get_tunable,
891         .set_tunable    = &vsc85xx_set_tunable,
892         .read_page      = &vsc85xx_phy_read_page,
893         .write_page     = &vsc85xx_phy_write_page,
894         .get_sset_count = &vsc85xx_get_sset_count,
895         .get_strings    = &vsc85xx_get_strings,
896         .get_stats      = &vsc85xx_get_stats,
897 },
898 {
899         .phy_id         = PHY_ID_VSC8541,
900         .name           = "Microsemi VSC8541 SyncE",
901         .phy_id_mask    = 0xfffffff0,
902         .features       = PHY_GBIT_FEATURES,
903         .flags          = PHY_HAS_INTERRUPT,
904         .soft_reset     = &genphy_soft_reset,
905         .config_init    = &vsc85xx_config_init,
906         .config_aneg    = &vsc85xx_config_aneg,
907         .aneg_done      = &genphy_aneg_done,
908         .read_status    = &vsc85xx_read_status,
909         .ack_interrupt  = &vsc85xx_ack_interrupt,
910         .config_intr    = &vsc85xx_config_intr,
911         .suspend        = &genphy_suspend,
912         .resume         = &genphy_resume,
913         .probe          = &vsc85xx_probe,
914         .set_wol        = &vsc85xx_wol_set,
915         .get_wol        = &vsc85xx_wol_get,
916         .get_tunable    = &vsc85xx_get_tunable,
917         .set_tunable    = &vsc85xx_set_tunable,
918         .read_page      = &vsc85xx_phy_read_page,
919         .write_page     = &vsc85xx_phy_write_page,
920         .get_sset_count = &vsc85xx_get_sset_count,
921         .get_strings    = &vsc85xx_get_strings,
922         .get_stats      = &vsc85xx_get_stats,
923 }
924
925 };
926
927 module_phy_driver(vsc85xx_driver);
928
929 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
930         { PHY_ID_VSC8530, 0xfffffff0, },
931         { PHY_ID_VSC8531, 0xfffffff0, },
932         { PHY_ID_VSC8540, 0xfffffff0, },
933         { PHY_ID_VSC8541, 0xfffffff0, },
934         { }
935 };
936
937 MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
938
939 MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
940 MODULE_AUTHOR("Nagaraju Lakkaraju");
941 MODULE_LICENSE("Dual MIT/GPL");