GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / net / phy / broadcom.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *      drivers/net/phy/broadcom.c
4  *
5  *      Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
6  *      transceivers.
7  *
8  *      Copyright (c) 2006  Maciej W. Rozycki
9  *
10  *      Inspired by code written by Amy Fong.
11  */
12
13 #include "bcm-phy-lib.h"
14 #include <linux/delay.h>
15 #include <linux/module.h>
16 #include <linux/phy.h>
17 #include <linux/brcmphy.h>
18 #include <linux/of.h>
19
20 #define BRCM_PHY_MODEL(phydev) \
21         ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
22
23 #define BRCM_PHY_REV(phydev) \
24         ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
25
26 MODULE_DESCRIPTION("Broadcom PHY driver");
27 MODULE_AUTHOR("Maciej W. Rozycki");
28 MODULE_LICENSE("GPL");
29
30 static int bcm54xx_config_clock_delay(struct phy_device *phydev)
31 {
32         int rc, val;
33
34         /* handling PHY's internal RX clock delay */
35         val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
36         val |= MII_BCM54XX_AUXCTL_MISC_WREN;
37         if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||
38             phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
39                 /* Disable RGMII RXC-RXD skew */
40                 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
41         }
42         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
43             phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
44                 /* Enable RGMII RXC-RXD skew */
45                 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
46         }
47         rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
48                                   val);
49         if (rc < 0)
50                 return rc;
51
52         /* handling PHY's internal TX clock delay */
53         val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
54         if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||
55             phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
56                 /* Disable internal TX clock delay */
57                 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
58         }
59         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
60             phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
61                 /* Enable internal TX clock delay */
62                 val |= BCM54810_SHD_CLK_CTL_GTXCLK_EN;
63         }
64         rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
65         if (rc < 0)
66                 return rc;
67
68         return 0;
69 }
70
71 static int bcm54210e_config_init(struct phy_device *phydev)
72 {
73         int val;
74
75         bcm54xx_config_clock_delay(phydev);
76
77         if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) {
78                 val = phy_read(phydev, MII_CTRL1000);
79                 val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
80                 phy_write(phydev, MII_CTRL1000, val);
81         }
82
83         return 0;
84 }
85
86 static int bcm54612e_config_init(struct phy_device *phydev)
87 {
88         int reg;
89
90         bcm54xx_config_clock_delay(phydev);
91
92         /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
93         if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {
94                 int err;
95
96                 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);
97                 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,
98                                         BCM54612E_LED4_CLK125OUT_EN | reg);
99
100                 if (err < 0)
101                         return err;
102         }
103
104         return 0;
105 }
106
107 static int bcm54616s_config_init(struct phy_device *phydev)
108 {
109         int rc, val;
110
111         if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
112             phydev->interface != PHY_INTERFACE_MODE_1000BASEX)
113                 return 0;
114
115         /* Ensure proper interface mode is selected. */
116         /* Disable RGMII mode */
117         val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
118         if (val < 0)
119                 return val;
120         val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN;
121         val |= MII_BCM54XX_AUXCTL_MISC_WREN;
122         rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
123                                   val);
124         if (rc < 0)
125                 return rc;
126
127         /* Select 1000BASE-X register set (primary SerDes) */
128         val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
129         if (val < 0)
130                 return val;
131         val |= BCM54XX_SHD_MODE_1000BX;
132         rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);
133         if (rc < 0)
134                 return rc;
135
136         /* Power down SerDes interface */
137         rc = phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
138         if (rc < 0)
139                 return rc;
140
141         /* Select proper interface mode */
142         val &= ~BCM54XX_SHD_INTF_SEL_MASK;
143         val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ?
144                 BCM54XX_SHD_INTF_SEL_SGMII :
145                 BCM54XX_SHD_INTF_SEL_GBIC;
146         rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);
147         if (rc < 0)
148                 return rc;
149
150         /* Power up SerDes interface */
151         rc = phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
152         if (rc < 0)
153                 return rc;
154
155         /* Select copper register set */
156         val &= ~BCM54XX_SHD_MODE_1000BX;
157         rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);
158         if (rc < 0)
159                 return rc;
160
161         /* Power up copper interface */
162         return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
163 }
164
165 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
166 static int bcm50610_a0_workaround(struct phy_device *phydev)
167 {
168         int err;
169
170         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
171                                 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
172                                 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
173         if (err < 0)
174                 return err;
175
176         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
177                                 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
178         if (err < 0)
179                 return err;
180
181         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
182                                 MII_BCM54XX_EXP_EXP75_VDACCTRL);
183         if (err < 0)
184                 return err;
185
186         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
187                                 MII_BCM54XX_EXP_EXP96_MYST);
188         if (err < 0)
189                 return err;
190
191         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
192                                 MII_BCM54XX_EXP_EXP97_MYST);
193
194         return err;
195 }
196
197 static int bcm54xx_phydsp_config(struct phy_device *phydev)
198 {
199         int err, err2;
200
201         /* Enable the SMDSP clock */
202         err = bcm54xx_auxctl_write(phydev,
203                                    MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
204                                    MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
205                                    MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
206         if (err < 0)
207                 return err;
208
209         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
210             BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
211                 /* Clear bit 9 to fix a phy interop issue. */
212                 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
213                                         MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
214                 if (err < 0)
215                         goto error;
216
217                 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
218                         err = bcm50610_a0_workaround(phydev);
219                         if (err < 0)
220                                 goto error;
221                 }
222         }
223
224         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
225                 int val;
226
227                 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
228                 if (val < 0)
229                         goto error;
230
231                 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
232                 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
233         }
234
235 error:
236         /* Disable the SMDSP clock */
237         err2 = bcm54xx_auxctl_write(phydev,
238                                     MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
239                                     MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
240
241         /* Return the first error reported. */
242         return err ? err : err2;
243 }
244
245 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
246 {
247         u32 orig;
248         int val;
249         bool clk125en = true;
250
251         /* Abort if we are using an untested phy. */
252         if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
253             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
254             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M &&
255             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54810 &&
256             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811)
257                 return;
258
259         val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
260         if (val < 0)
261                 return;
262
263         orig = val;
264
265         if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
266              BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
267             BRCM_PHY_REV(phydev) >= 0x3) {
268                 /*
269                  * Here, bit 0 _disables_ CLK125 when set.
270                  * This bit is set by default.
271                  */
272                 clk125en = false;
273         } else {
274                 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
275                         if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811) {
276                                 /* Here, bit 0 _enables_ CLK125 when set */
277                                 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
278                         }
279                         clk125en = false;
280                 }
281         }
282
283         if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
284                 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
285         else
286                 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
287
288         if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) {
289                 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810 ||
290                     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54811)
291                         val |= BCM54810_SHD_SCR3_TRDDAPD;
292                 else
293                         val |= BCM54XX_SHD_SCR3_TRDDAPD;
294         }
295
296         if (orig != val)
297                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
298
299         val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
300         if (val < 0)
301                 return;
302
303         orig = val;
304
305         if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
306                 val |= BCM54XX_SHD_APD_EN;
307         else
308                 val &= ~BCM54XX_SHD_APD_EN;
309
310         if (orig != val)
311                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
312 }
313
314 static int bcm54xx_config_init(struct phy_device *phydev)
315 {
316         int reg, err, val;
317
318         reg = phy_read(phydev, MII_BCM54XX_ECR);
319         if (reg < 0)
320                 return reg;
321
322         /* Mask interrupts globally.  */
323         reg |= MII_BCM54XX_ECR_IM;
324         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
325         if (err < 0)
326                 return err;
327
328         /* Unmask events we are interested in.  */
329         reg = ~(MII_BCM54XX_INT_DUPLEX |
330                 MII_BCM54XX_INT_SPEED |
331                 MII_BCM54XX_INT_LINK);
332         err = phy_write(phydev, MII_BCM54XX_IMR, reg);
333         if (err < 0)
334                 return err;
335
336         if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
337              BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
338             (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
339                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
340
341         bcm54xx_adjust_rxrefclk(phydev);
342
343         switch (BRCM_PHY_MODEL(phydev)) {
344         case PHY_ID_BCM50610:
345         case PHY_ID_BCM50610M:
346                 err = bcm54xx_config_clock_delay(phydev);
347                 break;
348         case PHY_ID_BCM54210E:
349                 err = bcm54210e_config_init(phydev);
350                 break;
351         case PHY_ID_BCM54612E:
352                 err = bcm54612e_config_init(phydev);
353                 break;
354         case PHY_ID_BCM54616S:
355                 err = bcm54616s_config_init(phydev);
356                 break;
357         case PHY_ID_BCM54810:
358                 /* For BCM54810, we need to disable BroadR-Reach function */
359                 val = bcm_phy_read_exp(phydev,
360                                        BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
361                 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
362                 err = bcm_phy_write_exp(phydev,
363                                         BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
364                                         val);
365                 break;
366         }
367         if (err)
368                 return err;
369
370         bcm54xx_phydsp_config(phydev);
371
372         /* Encode link speed into LED1 and LED3 pair (green/amber).
373          * Also flash these two LEDs on activity. This means configuring
374          * them for MULTICOLOR and encoding link/activity into them.
375          */
376         val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
377                 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
378         bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
379
380         val = BCM_LED_MULTICOLOR_IN_PHASE |
381                 BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
382                 BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
383         bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
384
385         return 0;
386 }
387
388 static int bcm54xx_resume(struct phy_device *phydev)
389 {
390         int ret;
391
392         /* Writes to register other than BMCR would be ignored
393          * unless we clear the PDOWN bit first
394          */
395         ret = genphy_resume(phydev);
396         if (ret < 0)
397                 return ret;
398
399         /* Upon exiting power down, the PHY remains in an internal reset state
400          * for 40us
401          */
402         fsleep(40);
403
404         return bcm54xx_config_init(phydev);
405 }
406
407 static int bcm54811_config_init(struct phy_device *phydev)
408 {
409         int err, reg;
410
411         /* Disable BroadR-Reach function. */
412         reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
413         reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
414         err = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
415                                 reg);
416         if (err < 0)
417                 return err;
418
419         err = bcm54xx_config_init(phydev);
420
421         /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
422         if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {
423                 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);
424                 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,
425                                         BCM54612E_LED4_CLK125OUT_EN | reg);
426                 if (err < 0)
427                         return err;
428         }
429
430         return err;
431 }
432
433 static int bcm5482_config_init(struct phy_device *phydev)
434 {
435         int err, reg;
436
437         err = bcm54xx_config_init(phydev);
438
439         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
440                 /*
441                  * Enable secondary SerDes and its use as an LED source
442                  */
443                 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
444                 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
445                                      reg |
446                                      BCM5482_SHD_SSD_LEDM |
447                                      BCM5482_SHD_SSD_EN);
448
449                 /*
450                  * Enable SGMII slave mode and auto-detection
451                  */
452                 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
453                 err = bcm_phy_read_exp(phydev, reg);
454                 if (err < 0)
455                         return err;
456                 err = bcm_phy_write_exp(phydev, reg, err |
457                                         BCM5482_SSD_SGMII_SLAVE_EN |
458                                         BCM5482_SSD_SGMII_SLAVE_AD);
459                 if (err < 0)
460                         return err;
461
462                 /*
463                  * Disable secondary SerDes powerdown
464                  */
465                 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
466                 err = bcm_phy_read_exp(phydev, reg);
467                 if (err < 0)
468                         return err;
469                 err = bcm_phy_write_exp(phydev, reg,
470                                         err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
471                 if (err < 0)
472                         return err;
473
474                 /*
475                  * Select 1000BASE-X register set (primary SerDes)
476                  */
477                 reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
478                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
479                                      reg | BCM54XX_SHD_MODE_1000BX);
480
481                 /*
482                  * LED1=ACTIVITYLED, LED3=LINKSPD[2]
483                  * (Use LED1 as secondary SerDes ACTIVITY LED)
484                  */
485                 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
486                         BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
487                         BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
488
489                 /*
490                  * Auto-negotiation doesn't seem to work quite right
491                  * in this mode, so we disable it and force it to the
492                  * right speed/duplex setting.  Only 'link status'
493                  * is important.
494                  */
495                 phydev->autoneg = AUTONEG_DISABLE;
496                 phydev->speed = SPEED_1000;
497                 phydev->duplex = DUPLEX_FULL;
498         }
499
500         return err;
501 }
502
503 static int bcm5482_read_status(struct phy_device *phydev)
504 {
505         int err;
506
507         err = genphy_read_status(phydev);
508
509         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
510                 /*
511                  * Only link status matters for 1000Base-X mode, so force
512                  * 1000 Mbit/s full-duplex status
513                  */
514                 if (phydev->link) {
515                         phydev->speed = SPEED_1000;
516                         phydev->duplex = DUPLEX_FULL;
517                 }
518         }
519
520         return err;
521 }
522
523 static int bcm5481_config_aneg(struct phy_device *phydev)
524 {
525         struct device_node *np = phydev->mdio.dev.of_node;
526         int ret;
527
528         /* Aneg firstly. */
529         ret = genphy_config_aneg(phydev);
530
531         /* Then we can set up the delay. */
532         bcm54xx_config_clock_delay(phydev);
533
534         if (of_property_read_bool(np, "enet-phy-lane-swap")) {
535                 /* Lane Swap - Undocumented register...magic! */
536                 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
537                                         0x11B);
538                 if (ret < 0)
539                         return ret;
540         }
541
542         return ret;
543 }
544
545 static int bcm54616s_probe(struct phy_device *phydev)
546 {
547         int val;
548
549         val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
550         if (val < 0)
551                 return val;
552
553         /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0]
554          * is 01b, and the link between PHY and its link partner can be
555          * either 1000Base-X or 100Base-FX.
556          * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX
557          * support is still missing as of now.
558          */
559         if ((val & BCM54XX_SHD_INTF_SEL_MASK) == BCM54XX_SHD_INTF_SEL_RGMII) {
560                 val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
561                 if (val < 0)
562                         return val;
563
564                 /* Bit 0 of the SerDes 100-FX Control register, when set
565                  * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
566                  * When this bit is set to 0, it sets the GMII/RGMII ->
567                  * 1000BASE-X configuration.
568                  */
569                 if (!(val & BCM54616S_100FX_MODE))
570                         phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
571
572                 phydev->port = PORT_FIBRE;
573         }
574
575         return 0;
576 }
577
578 static int bcm54616s_config_aneg(struct phy_device *phydev)
579 {
580         int ret;
581
582         /* Aneg firstly. */
583         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
584                 ret = genphy_c37_config_aneg(phydev);
585         else
586                 ret = genphy_config_aneg(phydev);
587
588         /* Then we can set up the delay. */
589         bcm54xx_config_clock_delay(phydev);
590
591         return ret;
592 }
593
594 static int bcm54616s_read_status(struct phy_device *phydev)
595 {
596         int err;
597
598         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
599                 err = genphy_c37_read_status(phydev);
600         else
601                 err = genphy_read_status(phydev);
602
603         return err;
604 }
605
606 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
607 {
608         int val;
609
610         val = phy_read(phydev, reg);
611         if (val < 0)
612                 return val;
613
614         return phy_write(phydev, reg, val | set);
615 }
616
617 static int brcm_fet_config_init(struct phy_device *phydev)
618 {
619         int reg, err, err2, brcmtest;
620
621         /* Reset the PHY to bring it to a known state. */
622         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
623         if (err < 0)
624                 return err;
625
626         /* The datasheet indicates the PHY needs up to 1us to complete a reset,
627          * build some slack here.
628          */
629         usleep_range(1000, 2000);
630
631         /* The PHY requires 65 MDC clock cycles to complete a write operation
632          * and turnaround the line properly.
633          *
634          * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac)
635          * may flag the lack of turn-around as a read failure. This is
636          * particularly true with this combination since the MDIO controller
637          * only used 64 MDC cycles. This is not a critical failure in this
638          * specific case and it has no functional impact otherwise, so we let
639          * that one go through. If there is a genuine bus error, the next read
640          * of MII_BRCM_FET_INTREG will error out.
641          */
642         err = phy_read(phydev, MII_BMCR);
643         if (err < 0 && err != -EIO)
644                 return err;
645
646         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
647         if (reg < 0)
648                 return reg;
649
650         /* Unmask events we are interested in and mask interrupts globally. */
651         reg = MII_BRCM_FET_IR_DUPLEX_EN |
652               MII_BRCM_FET_IR_SPEED_EN |
653               MII_BRCM_FET_IR_LINK_EN |
654               MII_BRCM_FET_IR_ENABLE |
655               MII_BRCM_FET_IR_MASK;
656
657         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
658         if (err < 0)
659                 return err;
660
661         /* Enable shadow register access */
662         brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
663         if (brcmtest < 0)
664                 return brcmtest;
665
666         reg = brcmtest | MII_BRCM_FET_BT_SRE;
667
668         err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
669         if (err < 0)
670                 return err;
671
672         /* Set the LED mode */
673         reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
674         if (reg < 0) {
675                 err = reg;
676                 goto done;
677         }
678
679         reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
680         reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
681
682         err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
683         if (err < 0)
684                 goto done;
685
686         /* Enable auto MDIX */
687         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
688                                        MII_BRCM_FET_SHDW_MC_FAME);
689         if (err < 0)
690                 goto done;
691
692         if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
693                 /* Enable auto power down */
694                 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
695                                                MII_BRCM_FET_SHDW_AS2_APDE);
696         }
697
698 done:
699         /* Disable shadow register access */
700         err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
701         if (!err)
702                 err = err2;
703
704         return err;
705 }
706
707 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
708 {
709         int reg;
710
711         /* Clear pending interrupts.  */
712         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
713         if (reg < 0)
714                 return reg;
715
716         return 0;
717 }
718
719 static int brcm_fet_config_intr(struct phy_device *phydev)
720 {
721         int reg, err;
722
723         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
724         if (reg < 0)
725                 return reg;
726
727         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
728                 reg &= ~MII_BRCM_FET_IR_MASK;
729         else
730                 reg |= MII_BRCM_FET_IR_MASK;
731
732         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
733         return err;
734 }
735
736 struct bcm53xx_phy_priv {
737         u64     *stats;
738 };
739
740 static int bcm53xx_phy_probe(struct phy_device *phydev)
741 {
742         struct bcm53xx_phy_priv *priv;
743
744         priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
745         if (!priv)
746                 return -ENOMEM;
747
748         phydev->priv = priv;
749
750         priv->stats = devm_kcalloc(&phydev->mdio.dev,
751                                    bcm_phy_get_sset_count(phydev), sizeof(u64),
752                                    GFP_KERNEL);
753         if (!priv->stats)
754                 return -ENOMEM;
755
756         return 0;
757 }
758
759 static void bcm53xx_phy_get_stats(struct phy_device *phydev,
760                                   struct ethtool_stats *stats, u64 *data)
761 {
762         struct bcm53xx_phy_priv *priv = phydev->priv;
763
764         bcm_phy_get_stats(phydev, priv->stats, stats, data);
765 }
766
767 static struct phy_driver broadcom_drivers[] = {
768 {
769         .phy_id         = PHY_ID_BCM5411,
770         .phy_id_mask    = 0xfffffff0,
771         .name           = "Broadcom BCM5411",
772         /* PHY_GBIT_FEATURES */
773         .config_init    = bcm54xx_config_init,
774         .ack_interrupt  = bcm_phy_ack_intr,
775         .config_intr    = bcm_phy_config_intr,
776 }, {
777         .phy_id         = PHY_ID_BCM5421,
778         .phy_id_mask    = 0xfffffff0,
779         .name           = "Broadcom BCM5421",
780         /* PHY_GBIT_FEATURES */
781         .config_init    = bcm54xx_config_init,
782         .ack_interrupt  = bcm_phy_ack_intr,
783         .config_intr    = bcm_phy_config_intr,
784 }, {
785         .phy_id         = PHY_ID_BCM54210E,
786         .phy_id_mask    = 0xfffffff0,
787         .name           = "Broadcom BCM54210E",
788         /* PHY_GBIT_FEATURES */
789         .config_init    = bcm54xx_config_init,
790         .ack_interrupt  = bcm_phy_ack_intr,
791         .config_intr    = bcm_phy_config_intr,
792 }, {
793         .phy_id         = PHY_ID_BCM5461,
794         .phy_id_mask    = 0xfffffff0,
795         .name           = "Broadcom BCM5461",
796         /* PHY_GBIT_FEATURES */
797         .config_init    = bcm54xx_config_init,
798         .ack_interrupt  = bcm_phy_ack_intr,
799         .config_intr    = bcm_phy_config_intr,
800 }, {
801         .phy_id         = PHY_ID_BCM54612E,
802         .phy_id_mask    = 0xfffffff0,
803         .name           = "Broadcom BCM54612E",
804         /* PHY_GBIT_FEATURES */
805         .config_init    = bcm54xx_config_init,
806         .ack_interrupt  = bcm_phy_ack_intr,
807         .config_intr    = bcm_phy_config_intr,
808 }, {
809         .phy_id         = PHY_ID_BCM54616S,
810         .phy_id_mask    = 0xfffffff0,
811         .name           = "Broadcom BCM54616S",
812         /* PHY_GBIT_FEATURES */
813         .soft_reset     = genphy_soft_reset,
814         .config_init    = bcm54xx_config_init,
815         .config_aneg    = bcm54616s_config_aneg,
816         .ack_interrupt  = bcm_phy_ack_intr,
817         .config_intr    = bcm_phy_config_intr,
818         .read_status    = bcm54616s_read_status,
819         .probe          = bcm54616s_probe,
820 }, {
821         .phy_id         = PHY_ID_BCM5464,
822         .phy_id_mask    = 0xfffffff0,
823         .name           = "Broadcom BCM5464",
824         /* PHY_GBIT_FEATURES */
825         .config_init    = bcm54xx_config_init,
826         .ack_interrupt  = bcm_phy_ack_intr,
827         .config_intr    = bcm_phy_config_intr,
828         .suspend        = genphy_suspend,
829         .resume         = genphy_resume,
830 }, {
831         .phy_id         = PHY_ID_BCM5481,
832         .phy_id_mask    = 0xfffffff0,
833         .name           = "Broadcom BCM5481",
834         /* PHY_GBIT_FEATURES */
835         .config_init    = bcm54xx_config_init,
836         .config_aneg    = bcm5481_config_aneg,
837         .ack_interrupt  = bcm_phy_ack_intr,
838         .config_intr    = bcm_phy_config_intr,
839 }, {
840         .phy_id         = PHY_ID_BCM54810,
841         .phy_id_mask    = 0xfffffff0,
842         .name           = "Broadcom BCM54810",
843         /* PHY_GBIT_FEATURES */
844         .config_init    = bcm54xx_config_init,
845         .config_aneg    = bcm5481_config_aneg,
846         .ack_interrupt  = bcm_phy_ack_intr,
847         .config_intr    = bcm_phy_config_intr,
848         .suspend        = genphy_suspend,
849         .resume         = bcm54xx_resume,
850 }, {
851         .phy_id         = PHY_ID_BCM54811,
852         .phy_id_mask    = 0xfffffff0,
853         .name           = "Broadcom BCM54811",
854         /* PHY_GBIT_FEATURES */
855         .config_init    = bcm54811_config_init,
856         .config_aneg    = bcm5481_config_aneg,
857         .ack_interrupt  = bcm_phy_ack_intr,
858         .config_intr    = bcm_phy_config_intr,
859         .suspend        = genphy_suspend,
860         .resume         = bcm54xx_resume,
861 }, {
862         .phy_id         = PHY_ID_BCM5482,
863         .phy_id_mask    = 0xfffffff0,
864         .name           = "Broadcom BCM5482",
865         /* PHY_GBIT_FEATURES */
866         .config_init    = bcm5482_config_init,
867         .read_status    = bcm5482_read_status,
868         .ack_interrupt  = bcm_phy_ack_intr,
869         .config_intr    = bcm_phy_config_intr,
870 }, {
871         .phy_id         = PHY_ID_BCM50610,
872         .phy_id_mask    = 0xfffffff0,
873         .name           = "Broadcom BCM50610",
874         /* PHY_GBIT_FEATURES */
875         .config_init    = bcm54xx_config_init,
876         .ack_interrupt  = bcm_phy_ack_intr,
877         .config_intr    = bcm_phy_config_intr,
878 }, {
879         .phy_id         = PHY_ID_BCM50610M,
880         .phy_id_mask    = 0xfffffff0,
881         .name           = "Broadcom BCM50610M",
882         /* PHY_GBIT_FEATURES */
883         .config_init    = bcm54xx_config_init,
884         .ack_interrupt  = bcm_phy_ack_intr,
885         .config_intr    = bcm_phy_config_intr,
886 }, {
887         .phy_id         = PHY_ID_BCM57780,
888         .phy_id_mask    = 0xfffffff0,
889         .name           = "Broadcom BCM57780",
890         /* PHY_GBIT_FEATURES */
891         .config_init    = bcm54xx_config_init,
892         .ack_interrupt  = bcm_phy_ack_intr,
893         .config_intr    = bcm_phy_config_intr,
894 }, {
895         .phy_id         = PHY_ID_BCMAC131,
896         .phy_id_mask    = 0xfffffff0,
897         .name           = "Broadcom BCMAC131",
898         /* PHY_BASIC_FEATURES */
899         .config_init    = brcm_fet_config_init,
900         .ack_interrupt  = brcm_fet_ack_interrupt,
901         .config_intr    = brcm_fet_config_intr,
902 }, {
903         .phy_id         = PHY_ID_BCM5241,
904         .phy_id_mask    = 0xfffffff0,
905         .name           = "Broadcom BCM5241",
906         /* PHY_BASIC_FEATURES */
907         .config_init    = brcm_fet_config_init,
908         .ack_interrupt  = brcm_fet_ack_interrupt,
909         .config_intr    = brcm_fet_config_intr,
910 }, {
911         .phy_id         = PHY_ID_BCM5395,
912         .phy_id_mask    = 0xfffffff0,
913         .name           = "Broadcom BCM5395",
914         .flags          = PHY_IS_INTERNAL,
915         /* PHY_GBIT_FEATURES */
916         .get_sset_count = bcm_phy_get_sset_count,
917         .get_strings    = bcm_phy_get_strings,
918         .get_stats      = bcm53xx_phy_get_stats,
919         .probe          = bcm53xx_phy_probe,
920 }, {
921         .phy_id         = PHY_ID_BCM53125,
922         .phy_id_mask    = 0xfffffff0,
923         .name           = "Broadcom BCM53125",
924         .flags          = PHY_IS_INTERNAL,
925         /* PHY_GBIT_FEATURES */
926         .get_sset_count = bcm_phy_get_sset_count,
927         .get_strings    = bcm_phy_get_strings,
928         .get_stats      = bcm53xx_phy_get_stats,
929         .probe          = bcm53xx_phy_probe,
930         .config_init    = bcm54xx_config_init,
931         .ack_interrupt  = bcm_phy_ack_intr,
932         .config_intr    = bcm_phy_config_intr,
933 }, {
934         .phy_id         = PHY_ID_BCM89610,
935         .phy_id_mask    = 0xfffffff0,
936         .name           = "Broadcom BCM89610",
937         /* PHY_GBIT_FEATURES */
938         .config_init    = bcm54xx_config_init,
939         .ack_interrupt  = bcm_phy_ack_intr,
940         .config_intr    = bcm_phy_config_intr,
941 } };
942
943 module_phy_driver(broadcom_drivers);
944
945 static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
946         { PHY_ID_BCM5411, 0xfffffff0 },
947         { PHY_ID_BCM5421, 0xfffffff0 },
948         { PHY_ID_BCM54210E, 0xfffffff0 },
949         { PHY_ID_BCM5461, 0xfffffff0 },
950         { PHY_ID_BCM54612E, 0xfffffff0 },
951         { PHY_ID_BCM54616S, 0xfffffff0 },
952         { PHY_ID_BCM5464, 0xfffffff0 },
953         { PHY_ID_BCM5481, 0xfffffff0 },
954         { PHY_ID_BCM54810, 0xfffffff0 },
955         { PHY_ID_BCM54811, 0xfffffff0 },
956         { PHY_ID_BCM5482, 0xfffffff0 },
957         { PHY_ID_BCM50610, 0xfffffff0 },
958         { PHY_ID_BCM50610M, 0xfffffff0 },
959         { PHY_ID_BCM57780, 0xfffffff0 },
960         { PHY_ID_BCMAC131, 0xfffffff0 },
961         { PHY_ID_BCM5241, 0xfffffff0 },
962         { PHY_ID_BCM5395, 0xfffffff0 },
963         { PHY_ID_BCM53125, 0xfffffff0 },
964         { PHY_ID_BCM89610, 0xfffffff0 },
965         { }
966 };
967
968 MODULE_DEVICE_TABLE(mdio, broadcom_tbl);