GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / net / phy / bcm7xxx.c
1 /*
2  * Broadcom BCM7xxx internal transceivers support.
3  *
4  * Copyright (C) 2014-2017 Broadcom
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11
12 #include <linux/module.h>
13 #include <linux/phy.h>
14 #include <linux/delay.h>
15 #include "bcm-phy-lib.h"
16 #include <linux/bitops.h>
17 #include <linux/brcmphy.h>
18 #include <linux/mdio.h>
19
20 /* Broadcom BCM7xxx internal PHY registers */
21
22 /* EPHY only register definitions */
23 #define MII_BCM7XXX_100TX_AUX_CTL       0x10
24 #define MII_BCM7XXX_100TX_FALSE_CAR     0x13
25 #define MII_BCM7XXX_100TX_DISC          0x14
26 #define MII_BCM7XXX_AUX_MODE            0x1d
27 #define  MII_BCM7XXX_64CLK_MDIO         BIT(12)
28 #define MII_BCM7XXX_TEST                0x1f
29 #define  MII_BCM7XXX_SHD_MODE_2         BIT(2)
30 #define MII_BCM7XXX_SHD_2_ADDR_CTRL     0xe
31 #define MII_BCM7XXX_SHD_2_CTRL_STAT     0xf
32 #define MII_BCM7XXX_SHD_2_BIAS_TRIM     0x1a
33 #define MII_BCM7XXX_SHD_3_PCS_CTRL      0x0
34 #define MII_BCM7XXX_SHD_3_PCS_STATUS    0x1
35 #define MII_BCM7XXX_SHD_3_EEE_CAP       0x2
36 #define MII_BCM7XXX_SHD_3_AN_EEE_ADV    0x3
37 #define MII_BCM7XXX_SHD_3_EEE_LP        0x4
38 #define MII_BCM7XXX_SHD_3_EEE_WK_ERR    0x5
39 #define MII_BCM7XXX_SHD_3_PCS_CTRL_2    0x6
40 #define  MII_BCM7XXX_PCS_CTRL_2_DEF     0x4400
41 #define MII_BCM7XXX_SHD_3_AN_STAT       0xb
42 #define  MII_BCM7XXX_AN_NULL_MSG_EN     BIT(0)
43 #define  MII_BCM7XXX_AN_EEE_EN          BIT(1)
44 #define MII_BCM7XXX_SHD_3_EEE_THRESH    0xe
45 #define  MII_BCM7XXX_EEE_THRESH_DEF     0x50
46 #define MII_BCM7XXX_SHD_3_TL4           0x23
47 #define  MII_BCM7XXX_TL4_RST_MSK        (BIT(2) | BIT(1))
48
49 /* 28nm only register definitions */
50 #define MISC_ADDR(base, channel)        base, channel
51
52 #define DSP_TAP10                       MISC_ADDR(0x0a, 0)
53 #define PLL_PLLCTRL_1                   MISC_ADDR(0x32, 1)
54 #define PLL_PLLCTRL_2                   MISC_ADDR(0x32, 2)
55 #define PLL_PLLCTRL_4                   MISC_ADDR(0x33, 0)
56
57 #define AFE_RXCONFIG_0                  MISC_ADDR(0x38, 0)
58 #define AFE_RXCONFIG_1                  MISC_ADDR(0x38, 1)
59 #define AFE_RXCONFIG_2                  MISC_ADDR(0x38, 2)
60 #define AFE_RX_LP_COUNTER               MISC_ADDR(0x38, 3)
61 #define AFE_TX_CONFIG                   MISC_ADDR(0x39, 0)
62 #define AFE_VDCA_ICTRL_0                MISC_ADDR(0x39, 1)
63 #define AFE_VDAC_OTHERS_0               MISC_ADDR(0x39, 3)
64 #define AFE_HPF_TRIM_OTHERS             MISC_ADDR(0x3a, 0)
65
66 struct bcm7xxx_phy_priv {
67         u64     *stats;
68 };
69
70 static void r_rc_cal_reset(struct phy_device *phydev)
71 {
72         /* Reset R_CAL/RC_CAL Engine */
73         bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010);
74
75         /* Disable Reset R_AL/RC_CAL Engine */
76         bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000);
77 }
78
79 static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
80 {
81         /* Increase VCO range to prevent unlocking problem of PLL at low
82          * temp
83          */
84         bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
85
86         /* Change Ki to 011 */
87         bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
88
89         /* Disable loading of TVCO buffer to bandgap, set bandgap trim
90          * to 111
91          */
92         bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
93
94         /* Adjust bias current trim by -3 */
95         bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b);
96
97         /* Switch to CORE_BASE1E */
98         phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd);
99
100         r_rc_cal_reset(phydev);
101
102         /* write AFE_RXCONFIG_0 */
103         bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
104
105         /* write AFE_RXCONFIG_1 */
106         bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
107
108         /* write AFE_RX_LP_COUNTER */
109         bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
110
111         /* write AFE_HPF_TRIM_OTHERS */
112         bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
113
114         /* write AFTE_TX_CONFIG */
115         bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
116
117         return 0;
118 }
119
120 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
121 {
122         /* AFE_RXCONFIG_0 */
123         bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
124
125         /* AFE_RXCONFIG_1 */
126         bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
127
128         /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
129         bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
130
131         /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
132         bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
133
134         /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
135         bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
136
137         /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
138         bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
139
140         /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
141         bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
142
143         /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
144          * offset for HT=0 code
145          */
146         bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
147
148         /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
149         phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
150
151         /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
152         bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
153
154         /* Reset R_CAL/RC_CAL engine */
155         r_rc_cal_reset(phydev);
156
157         return 0;
158 }
159
160 static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
161 {
162         /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
163         bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
164
165         /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
166         bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
167
168         /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
169         bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
170
171         /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
172          * offset for HT=0 code
173          */
174         bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
175
176         /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
177         phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
178
179         /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
180         bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
181
182         /* Reset R_CAL/RC_CAL engine */
183         r_rc_cal_reset(phydev);
184
185         return 0;
186 }
187
188 static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev)
189 {
190         /* +1 RC_CAL codes for RL centering for both LT and HT conditions */
191         bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
192
193         /* Cut master bias current by 2% to compensate for RC_CAL offset */
194         bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
195
196         /* Improve hybrid leakage */
197         bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
198
199         /* Change rx_on_tune 8 to 0xf */
200         bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
201
202         /* Change 100Tx EEE bandwidth */
203         bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
204
205         /* Enable ffe zero detection for Vitesse interoperability */
206         bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015);
207
208         r_rc_cal_reset(phydev);
209
210         return 0;
211 }
212
213 static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
214 {
215         u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
216         u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
217         u8 count;
218         int ret = 0;
219
220         /* Newer devices have moved the revision information back into a
221          * standard location in MII_PHYS_ID[23]
222          */
223         if (rev == 0)
224                 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
225
226         pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
227                      phydev_name(phydev), phydev->drv->name, rev, patch);
228
229         /* Dummy read to a register to workaround an issue upon reset where the
230          * internal inverter may not allow the first MDIO transaction to pass
231          * the MDIO management controller and make us return 0xffff for such
232          * reads.
233          */
234         phy_read(phydev, MII_BMSR);
235
236         switch (rev) {
237         case 0xb0:
238                 ret = bcm7xxx_28nm_b0_afe_config_init(phydev);
239                 break;
240         case 0xd0:
241                 ret = bcm7xxx_28nm_d0_afe_config_init(phydev);
242                 break;
243         case 0xe0:
244         case 0xf0:
245         /* Rev G0 introduces a roll over */
246         case 0x10:
247                 ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
248                 break;
249         case 0x01:
250                 ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
251                 break;
252         default:
253                 break;
254         }
255
256         if (ret)
257                 return ret;
258
259         ret = bcm_phy_downshift_get(phydev, &count);
260         if (ret)
261                 return ret;
262
263         /* Only enable EEE if Wirespeed/downshift is disabled */
264         ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
265         if (ret)
266                 return ret;
267
268         return bcm_phy_enable_apd(phydev, true);
269 }
270
271 static int bcm7xxx_28nm_resume(struct phy_device *phydev)
272 {
273         int ret;
274
275         /* Re-apply workarounds coming out suspend/resume */
276         ret = bcm7xxx_28nm_config_init(phydev);
277         if (ret)
278                 return ret;
279
280         /* 28nm Gigabit PHYs come out of reset without any half-duplex
281          * or "hub" compliant advertised mode, fix that. This does not
282          * cause any problems with the PHY library since genphy_config_aneg()
283          * gracefully handles auto-negotiated and forced modes.
284          */
285         return genphy_config_aneg(phydev);
286 }
287
288 static int phy_set_clr_bits(struct phy_device *dev, int location,
289                                         int set_mask, int clr_mask)
290 {
291         int v, ret;
292
293         v = phy_read(dev, location);
294         if (v < 0)
295                 return v;
296
297         v &= ~clr_mask;
298         v |= set_mask;
299
300         ret = phy_write(dev, location, v);
301         if (ret < 0)
302                 return ret;
303
304         return v;
305 }
306
307 static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
308 {
309         int ret;
310
311         /* set shadow mode 2 */
312         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
313                                MII_BCM7XXX_SHD_MODE_2, 0);
314         if (ret < 0)
315                 return ret;
316
317         /* Set current trim values INT_trim = -1, Ext_trim =0 */
318         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
319         if (ret < 0)
320                 goto reset_shadow_mode;
321
322         /* Cal reset */
323         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
324                         MII_BCM7XXX_SHD_3_TL4);
325         if (ret < 0)
326                 goto reset_shadow_mode;
327         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
328                                MII_BCM7XXX_TL4_RST_MSK, 0);
329         if (ret < 0)
330                 goto reset_shadow_mode;
331
332         /* Cal reset disable */
333         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
334                         MII_BCM7XXX_SHD_3_TL4);
335         if (ret < 0)
336                 goto reset_shadow_mode;
337         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
338                                0, MII_BCM7XXX_TL4_RST_MSK);
339         if (ret < 0)
340                 goto reset_shadow_mode;
341
342 reset_shadow_mode:
343         /* reset shadow mode 2 */
344         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
345                                MII_BCM7XXX_SHD_MODE_2);
346         if (ret < 0)
347                 return ret;
348
349         return 0;
350 }
351
352 /* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */
353 static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
354 {
355         int ret;
356
357         /* set shadow mode 1 */
358         ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST,
359                                MII_BRCM_FET_BT_SRE, 0);
360         if (ret < 0)
361                 return ret;
362
363         /* Enable auto-power down */
364         ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
365                                MII_BRCM_FET_SHDW_AS2_APDE, 0);
366         if (ret < 0)
367                 return ret;
368
369         /* reset shadow mode 1 */
370         ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0,
371                                MII_BRCM_FET_BT_SRE);
372         if (ret < 0)
373                 return ret;
374
375         return 0;
376 }
377
378 static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev)
379 {
380         int ret;
381
382         /* set shadow mode 2 */
383         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
384                                MII_BCM7XXX_SHD_MODE_2, 0);
385         if (ret < 0)
386                 return ret;
387
388         /* Advertise supported modes */
389         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
390                         MII_BCM7XXX_SHD_3_AN_EEE_ADV);
391         if (ret < 0)
392                 goto reset_shadow_mode;
393         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
394                         MDIO_EEE_100TX);
395         if (ret < 0)
396                 goto reset_shadow_mode;
397
398         /* Restore Defaults */
399         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
400                         MII_BCM7XXX_SHD_3_PCS_CTRL_2);
401         if (ret < 0)
402                 goto reset_shadow_mode;
403         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
404                         MII_BCM7XXX_PCS_CTRL_2_DEF);
405         if (ret < 0)
406                 goto reset_shadow_mode;
407
408         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
409                         MII_BCM7XXX_SHD_3_EEE_THRESH);
410         if (ret < 0)
411                 goto reset_shadow_mode;
412         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
413                         MII_BCM7XXX_EEE_THRESH_DEF);
414         if (ret < 0)
415                 goto reset_shadow_mode;
416
417         /* Enable EEE autonegotiation */
418         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
419                         MII_BCM7XXX_SHD_3_AN_STAT);
420         if (ret < 0)
421                 goto reset_shadow_mode;
422         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
423                         (MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN));
424         if (ret < 0)
425                 goto reset_shadow_mode;
426
427 reset_shadow_mode:
428         /* reset shadow mode 2 */
429         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
430                                MII_BCM7XXX_SHD_MODE_2);
431         if (ret < 0)
432                 return ret;
433
434         /* Restart autoneg */
435         phy_write(phydev, MII_BMCR,
436                   (BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART));
437
438         return 0;
439 }
440
441 static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
442 {
443         u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
444         int ret = 0;
445
446         pr_info_once("%s: %s PHY revision: 0x%02x\n",
447                      phydev_name(phydev), phydev->drv->name, rev);
448
449         /* Dummy read to a register to workaround a possible issue upon reset
450          * where the internal inverter may not allow the first MDIO transaction
451          * to pass the MDIO management controller and make us return 0xffff for
452          * such reads.
453          */
454         phy_read(phydev, MII_BMSR);
455
456         /* Apply AFE software work-around if necessary */
457         if (rev == 0x01) {
458                 ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev);
459                 if (ret)
460                         return ret;
461         }
462
463         ret = bcm7xxx_28nm_ephy_eee_enable(phydev);
464         if (ret)
465                 return ret;
466
467         return bcm7xxx_28nm_ephy_apd_enable(phydev);
468 }
469
470 #define MII_BCM7XXX_REG_INVALID 0xff
471
472 static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
473 {
474         switch (regnum) {
475         case MDIO_CTRL1:
476                 return MII_BCM7XXX_SHD_3_PCS_CTRL;
477         case MDIO_STAT1:
478                 return MII_BCM7XXX_SHD_3_PCS_STATUS;
479         case MDIO_PCS_EEE_ABLE:
480                 return MII_BCM7XXX_SHD_3_EEE_CAP;
481         case MDIO_AN_EEE_ADV:
482                 return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
483         case MDIO_AN_EEE_LPABLE:
484                 return MII_BCM7XXX_SHD_3_EEE_LP;
485         case MDIO_PCS_EEE_WK_ERR:
486                 return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
487         default:
488                 return MII_BCM7XXX_REG_INVALID;
489         }
490 }
491
492 static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
493 {
494         return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
495 }
496
497 static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
498                                       int devnum, u16 regnum)
499 {
500         u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
501         int ret;
502
503         if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
504             shd == MII_BCM7XXX_REG_INVALID)
505                 return -EOPNOTSUPP;
506
507         /* set shadow mode 2 */
508         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
509                                MII_BCM7XXX_SHD_MODE_2, 0);
510         if (ret < 0)
511                 return ret;
512
513         /* Access the desired shadow register address */
514         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
515         if (ret < 0)
516                 goto reset_shadow_mode;
517
518         ret = phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
519
520 reset_shadow_mode:
521         /* reset shadow mode 2 */
522         phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
523                          MII_BCM7XXX_SHD_MODE_2);
524         return ret;
525 }
526
527 static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
528                                        int devnum, u16 regnum, u16 val)
529 {
530         u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
531         int ret;
532
533         if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
534             shd == MII_BCM7XXX_REG_INVALID)
535                 return -EOPNOTSUPP;
536
537         /* set shadow mode 2 */
538         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
539                                MII_BCM7XXX_SHD_MODE_2, 0);
540         if (ret < 0)
541                 return ret;
542
543         /* Access the desired shadow register address */
544         ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
545         if (ret < 0)
546                 goto reset_shadow_mode;
547
548         /* Write the desired value in the shadow register */
549         phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
550
551 reset_shadow_mode:
552         /* reset shadow mode 2 */
553         return phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
554                                 MII_BCM7XXX_SHD_MODE_2);
555 }
556
557 static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
558 {
559         int ret;
560
561         /* Re-apply workarounds coming out suspend/resume */
562         ret = bcm7xxx_28nm_ephy_config_init(phydev);
563         if (ret)
564                 return ret;
565
566         return genphy_config_aneg(phydev);
567 }
568
569 static int bcm7xxx_config_init(struct phy_device *phydev)
570 {
571         int ret;
572
573         /* Enable 64 clock MDIO */
574         phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO);
575         phy_read(phydev, MII_BCM7XXX_AUX_MODE);
576
577         /* set shadow mode 2 */
578         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
579                         MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
580         if (ret < 0)
581                 return ret;
582
583         /* set iddq_clkbias */
584         phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
585         udelay(10);
586
587         /* reset iddq_clkbias */
588         phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
589
590         phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
591
592         /* reset shadow mode 2 */
593         ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2);
594         if (ret < 0)
595                 return ret;
596
597         return 0;
598 }
599
600 /* Workaround for putting the PHY in IDDQ mode, required
601  * for all BCM7XXX 40nm and 65nm PHYs
602  */
603 static int bcm7xxx_suspend(struct phy_device *phydev)
604 {
605         int ret;
606         static const struct bcm7xxx_regs {
607                 int reg;
608                 u16 value;
609         } bcm7xxx_suspend_cfg[] = {
610                 { MII_BCM7XXX_TEST, 0x008b },
611                 { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 },
612                 { MII_BCM7XXX_100TX_DISC, 0x7000 },
613                 { MII_BCM7XXX_TEST, 0x000f },
614                 { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 },
615                 { MII_BCM7XXX_TEST, 0x000b },
616         };
617         unsigned int i;
618
619         for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) {
620                 ret = phy_write(phydev,
621                                 bcm7xxx_suspend_cfg[i].reg,
622                                 bcm7xxx_suspend_cfg[i].value);
623                 if (ret)
624                         return ret;
625         }
626
627         return 0;
628 }
629
630 static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev,
631                                     struct ethtool_tunable *tuna,
632                                     void *data)
633 {
634         switch (tuna->id) {
635         case ETHTOOL_PHY_DOWNSHIFT:
636                 return bcm_phy_downshift_get(phydev, (u8 *)data);
637         default:
638                 return -EOPNOTSUPP;
639         }
640 }
641
642 static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev,
643                                     struct ethtool_tunable *tuna,
644                                     const void *data)
645 {
646         u8 count = *(u8 *)data;
647         int ret;
648
649         switch (tuna->id) {
650         case ETHTOOL_PHY_DOWNSHIFT:
651                 ret = bcm_phy_downshift_set(phydev, count);
652                 break;
653         default:
654                 return -EOPNOTSUPP;
655         }
656
657         if (ret)
658                 return ret;
659
660         /* Disable EEE advertisment since this prevents the PHY
661          * from successfully linking up, trigger auto-negotiation restart
662          * to let the MAC decide what to do.
663          */
664         ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
665         if (ret)
666                 return ret;
667
668         return genphy_restart_aneg(phydev);
669 }
670
671 static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
672                                        struct ethtool_stats *stats, u64 *data)
673 {
674         struct bcm7xxx_phy_priv *priv = phydev->priv;
675
676         bcm_phy_get_stats(phydev, priv->stats, stats, data);
677 }
678
679 static int bcm7xxx_28nm_probe(struct phy_device *phydev)
680 {
681         struct bcm7xxx_phy_priv *priv;
682
683         priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
684         if (!priv)
685                 return -ENOMEM;
686
687         phydev->priv = priv;
688
689         priv->stats = devm_kcalloc(&phydev->mdio.dev,
690                                    bcm_phy_get_sset_count(phydev), sizeof(u64),
691                                    GFP_KERNEL);
692         if (!priv->stats)
693                 return -ENOMEM;
694
695         return 0;
696 }
697
698 #define BCM7XXX_28NM_GPHY(_oui, _name)                                  \
699 {                                                                       \
700         .phy_id         = (_oui),                                       \
701         .phy_id_mask    = 0xfffffff0,                                   \
702         .name           = _name,                                        \
703         .features       = PHY_GBIT_FEATURES,                            \
704         .flags          = PHY_IS_INTERNAL,                              \
705         .config_init    = bcm7xxx_28nm_config_init,                     \
706         .config_aneg    = genphy_config_aneg,                           \
707         .read_status    = genphy_read_status,                           \
708         .resume         = bcm7xxx_28nm_resume,                          \
709         .get_tunable    = bcm7xxx_28nm_get_tunable,                     \
710         .set_tunable    = bcm7xxx_28nm_set_tunable,                     \
711         .get_sset_count = bcm_phy_get_sset_count,                       \
712         .get_strings    = bcm_phy_get_strings,                          \
713         .get_stats      = bcm7xxx_28nm_get_phy_stats,                   \
714         .probe          = bcm7xxx_28nm_probe,                           \
715 }
716
717 #define BCM7XXX_28NM_EPHY(_oui, _name)                                  \
718 {                                                                       \
719         .phy_id         = (_oui),                                       \
720         .phy_id_mask    = 0xfffffff0,                                   \
721         .name           = _name,                                        \
722         .features       = PHY_BASIC_FEATURES,                           \
723         .flags          = PHY_IS_INTERNAL,                              \
724         .config_init    = bcm7xxx_28nm_ephy_config_init,                \
725         .config_aneg    = genphy_config_aneg,                           \
726         .read_status    = genphy_read_status,                           \
727         .resume         = bcm7xxx_28nm_ephy_resume,                     \
728         .get_sset_count = bcm_phy_get_sset_count,                       \
729         .get_strings    = bcm_phy_get_strings,                          \
730         .get_stats      = bcm7xxx_28nm_get_phy_stats,                   \
731         .probe          = bcm7xxx_28nm_probe,                           \
732         .read_mmd       = bcm7xxx_28nm_ephy_read_mmd,                   \
733         .write_mmd      = bcm7xxx_28nm_ephy_write_mmd,                  \
734 }
735
736 #define BCM7XXX_40NM_EPHY(_oui, _name)                                  \
737 {                                                                       \
738         .phy_id         = (_oui),                                       \
739         .phy_id_mask    = 0xfffffff0,                                   \
740         .name           = _name,                                        \
741         .features       = PHY_BASIC_FEATURES,                           \
742         .flags          = PHY_IS_INTERNAL,                              \
743         .config_init    = bcm7xxx_config_init,                          \
744         .config_aneg    = genphy_config_aneg,                           \
745         .read_status    = genphy_read_status,                           \
746         .suspend        = bcm7xxx_suspend,                              \
747         .resume         = bcm7xxx_config_init,                          \
748 }
749
750 static struct phy_driver bcm7xxx_driver[] = {
751         BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
752         BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"),
753         BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"),
754         BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"),
755         BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
756         BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
757         BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
758         BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"),
759         BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
760         BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"),
761         BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"),
762         BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"),
763         BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"),
764         BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"),
765         BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"),
766         BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"),
767 };
768
769 static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
770         { PHY_ID_BCM7250, 0xfffffff0, },
771         { PHY_ID_BCM7260, 0xfffffff0, },
772         { PHY_ID_BCM7268, 0xfffffff0, },
773         { PHY_ID_BCM7271, 0xfffffff0, },
774         { PHY_ID_BCM7278, 0xfffffff0, },
775         { PHY_ID_BCM7364, 0xfffffff0, },
776         { PHY_ID_BCM7366, 0xfffffff0, },
777         { PHY_ID_BCM7346, 0xfffffff0, },
778         { PHY_ID_BCM7362, 0xfffffff0, },
779         { PHY_ID_BCM7425, 0xfffffff0, },
780         { PHY_ID_BCM7429, 0xfffffff0, },
781         { PHY_ID_BCM74371, 0xfffffff0, },
782         { PHY_ID_BCM7439, 0xfffffff0, },
783         { PHY_ID_BCM7435, 0xfffffff0, },
784         { PHY_ID_BCM7445, 0xfffffff0, },
785         { }
786 };
787
788 module_phy_driver(bcm7xxx_driver);
789
790 MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl);
791
792 MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver");
793 MODULE_LICENSE("GPL");
794 MODULE_AUTHOR("Broadcom Corporation");