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 * Broadcom BCM54810, BCM54811 BroadR-Reach transceivers.
9 *
10 * Copyright (c) 2006 Maciej W. Rozycki
11 *
12 * Inspired by code written by Amy Fong.
13 */
14
15 #include "bcm-phy-lib.h"
16 #include <linux/delay.h>
17 #include <linux/module.h>
18 #include <linux/phy.h>
19 #include <linux/device.h>
20 #include <linux/brcmphy.h>
21 #include <linux/of.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/gpio/consumer.h>
25
26 #define BRCM_PHY_REV(phydev) \
27 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
28
29 MODULE_DESCRIPTION("Broadcom PHY driver");
30 MODULE_AUTHOR("Maciej W. Rozycki");
31 MODULE_LICENSE("GPL");
32
33 struct bcm54xx_phy_priv {
34 u64 *stats;
35 struct bcm_ptp_private *ptp;
36 int wake_irq;
37 bool wake_irq_enabled;
38 bool brr_mode;
39 };
40
41 /* Link modes for BCM58411 PHY */
42 static const int bcm54811_linkmodes[] = {
43 ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
44 ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,
45 ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
46 ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
47 ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
48 ETHTOOL_LINK_MODE_100baseT_Full_BIT,
49 ETHTOOL_LINK_MODE_100baseT_Half_BIT,
50 ETHTOOL_LINK_MODE_10baseT_Full_BIT,
51 ETHTOOL_LINK_MODE_10baseT_Half_BIT
52 };
53
54 /* Long-Distance Signaling (BroadR-Reach mode aneg) relevant linkmode bits */
55 static const int lds_br_bits[] = {
56 ETHTOOL_LINK_MODE_Autoneg_BIT,
57 ETHTOOL_LINK_MODE_Pause_BIT,
58 ETHTOOL_LINK_MODE_Asym_Pause_BIT,
59 ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,
60 ETHTOOL_LINK_MODE_100baseT1_Full_BIT
61 };
62
bcm54xx_phy_can_wakeup(struct phy_device * phydev)63 static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev)
64 {
65 struct bcm54xx_phy_priv *priv = phydev->priv;
66
67 return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0;
68 }
69
bcm54xx_config_clock_delay(struct phy_device * phydev)70 static int bcm54xx_config_clock_delay(struct phy_device *phydev)
71 {
72 int rc, val;
73
74 /* handling PHY's internal RX clock delay */
75 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
76 val |= MII_BCM54XX_AUXCTL_MISC_WREN;
77 if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||
78 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
79 /* Disable RGMII RXC-RXD skew */
80 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
81 }
82 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
83 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
84 /* Enable RGMII RXC-RXD skew */
85 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
86 }
87 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
88 val);
89 if (rc < 0)
90 return rc;
91
92 /* handling PHY's internal TX clock delay */
93 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
94 if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||
95 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
96 /* Disable internal TX clock delay */
97 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
98 }
99 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
100 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
101 /* Enable internal TX clock delay */
102 val |= BCM54810_SHD_CLK_CTL_GTXCLK_EN;
103 }
104 rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
105 if (rc < 0)
106 return rc;
107
108 return 0;
109 }
110
bcm54210e_config_init(struct phy_device * phydev)111 static int bcm54210e_config_init(struct phy_device *phydev)
112 {
113 int val;
114
115 bcm54xx_config_clock_delay(phydev);
116
117 if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) {
118 val = phy_read(phydev, MII_CTRL1000);
119 val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
120 phy_write(phydev, MII_CTRL1000, val);
121 }
122
123 return 0;
124 }
125
bcm54612e_config_init(struct phy_device * phydev)126 static int bcm54612e_config_init(struct phy_device *phydev)
127 {
128 int reg;
129
130 bcm54xx_config_clock_delay(phydev);
131
132 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
133 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {
134 int err;
135
136 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);
137 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,
138 BCM54612E_LED4_CLK125OUT_EN | reg);
139
140 if (err < 0)
141 return err;
142 }
143
144 return 0;
145 }
146
bcm54616s_config_init(struct phy_device * phydev)147 static int bcm54616s_config_init(struct phy_device *phydev)
148 {
149 int rc, val;
150
151 if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
152 phydev->interface != PHY_INTERFACE_MODE_1000BASEX)
153 return 0;
154
155 /* Ensure proper interface mode is selected. */
156 /* Disable RGMII mode */
157 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
158 if (val < 0)
159 return val;
160 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN;
161 val |= MII_BCM54XX_AUXCTL_MISC_WREN;
162 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
163 val);
164 if (rc < 0)
165 return rc;
166
167 /* Select 1000BASE-X register set (primary SerDes) */
168 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
169 if (val < 0)
170 return val;
171 val |= BCM54XX_SHD_MODE_1000BX;
172 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);
173 if (rc < 0)
174 return rc;
175
176 /* Power down SerDes interface */
177 rc = phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
178 if (rc < 0)
179 return rc;
180
181 /* Select proper interface mode */
182 val &= ~BCM54XX_SHD_INTF_SEL_MASK;
183 val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ?
184 BCM54XX_SHD_INTF_SEL_SGMII :
185 BCM54XX_SHD_INTF_SEL_GBIC;
186 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);
187 if (rc < 0)
188 return rc;
189
190 /* Power up SerDes interface */
191 rc = phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
192 if (rc < 0)
193 return rc;
194
195 /* Select copper register set */
196 val &= ~BCM54XX_SHD_MODE_1000BX;
197 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);
198 if (rc < 0)
199 return rc;
200
201 /* Power up copper interface */
202 return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
203 }
204
205 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
bcm50610_a0_workaround(struct phy_device * phydev)206 static int bcm50610_a0_workaround(struct phy_device *phydev)
207 {
208 int err;
209
210 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
211 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
212 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
213 if (err < 0)
214 return err;
215
216 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
217 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
218 if (err < 0)
219 return err;
220
221 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
222 MII_BCM54XX_EXP_EXP75_VDACCTRL);
223 if (err < 0)
224 return err;
225
226 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
227 MII_BCM54XX_EXP_EXP96_MYST);
228 if (err < 0)
229 return err;
230
231 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
232 MII_BCM54XX_EXP_EXP97_MYST);
233
234 return err;
235 }
236
bcm54xx_phydsp_config(struct phy_device * phydev)237 static int bcm54xx_phydsp_config(struct phy_device *phydev)
238 {
239 int err, err2;
240
241 /* Enable the SMDSP clock */
242 err = bcm54xx_auxctl_write(phydev,
243 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
244 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
245 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
246 if (err < 0)
247 return err;
248
249 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) ||
250 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M)) {
251 /* Clear bit 9 to fix a phy interop issue. */
252 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
253 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
254 if (err < 0)
255 goto error;
256
257 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
258 err = bcm50610_a0_workaround(phydev);
259 if (err < 0)
260 goto error;
261 }
262 }
263
264 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM57780)) {
265 int val;
266
267 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
268 if (val < 0)
269 goto error;
270
271 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
272 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
273 }
274
275 error:
276 /* Disable the SMDSP clock */
277 err2 = bcm54xx_auxctl_write(phydev,
278 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
279 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
280
281 /* Return the first error reported. */
282 return err ? err : err2;
283 }
284
bcm54xx_adjust_rxrefclk(struct phy_device * phydev)285 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
286 {
287 u32 orig;
288 int val;
289 bool clk125en = true;
290
291 /* Abort if we are using an untested phy. */
292 if (!(phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM57780) ||
293 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) ||
294 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M) ||
295 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54210E) ||
296 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54810) ||
297 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811)))
298 return;
299
300 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
301 if (val < 0)
302 return;
303
304 orig = val;
305
306 if ((phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) ||
307 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M)) &&
308 BRCM_PHY_REV(phydev) >= 0x3) {
309 /*
310 * Here, bit 0 _disables_ CLK125 when set.
311 * This bit is set by default.
312 */
313 clk125en = false;
314 } else {
315 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
316 if (!phy_id_compare_model(phydev->drv->phy_id,
317 PHY_ID_BCM54811)) {
318 /* Here, bit 0 _enables_ CLK125 when set */
319 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
320 }
321 clk125en = false;
322 }
323 }
324
325 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
326 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
327 else
328 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
329
330 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) {
331 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54210E) ||
332 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54810) ||
333 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811))
334 val |= BCM54XX_SHD_SCR3_RXCTXC_DIS;
335 else
336 val |= BCM54XX_SHD_SCR3_TRDDAPD;
337 }
338
339 if (orig != val)
340 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
341
342 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
343 if (val < 0)
344 return;
345
346 orig = val;
347
348 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
349 val |= BCM54XX_SHD_APD_EN;
350 else
351 val &= ~BCM54XX_SHD_APD_EN;
352
353 if (orig != val)
354 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
355 }
356
bcm54xx_ptp_stop(struct phy_device * phydev)357 static void bcm54xx_ptp_stop(struct phy_device *phydev)
358 {
359 struct bcm54xx_phy_priv *priv = phydev->priv;
360
361 if (priv->ptp)
362 bcm_ptp_stop(priv->ptp);
363 }
364
bcm54xx_ptp_config_init(struct phy_device * phydev)365 static void bcm54xx_ptp_config_init(struct phy_device *phydev)
366 {
367 struct bcm54xx_phy_priv *priv = phydev->priv;
368
369 if (priv->ptp)
370 bcm_ptp_config_init(phydev);
371 }
372
bcm5481x_set_brrmode(struct phy_device * phydev,bool on)373 static int bcm5481x_set_brrmode(struct phy_device *phydev, bool on)
374 {
375 int reg;
376 int err;
377 u16 val;
378
379 reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
380
381 if (reg < 0)
382 return reg;
383
384 if (on)
385 reg |= BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
386 else
387 reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
388
389 err = bcm_phy_write_exp(phydev,
390 BCM54810_EXP_BROADREACH_LRE_MISC_CTL, reg);
391 if (err)
392 return err;
393
394 /* Ensure LRE or IEEE register set is accessed according to the brr
395 * on/off, thus set the override
396 */
397 val = BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_EN;
398 if (!on)
399 val |= BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_OVERRIDE_VAL;
400
401 return bcm_phy_write_exp(phydev,
402 BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL, val);
403 }
404
bcm54811_config_init(struct phy_device * phydev)405 static int bcm54811_config_init(struct phy_device *phydev)
406 {
407 struct bcm54xx_phy_priv *priv = phydev->priv;
408 int err, reg, exp_sync_ethernet, aux_rgmii_en;
409
410 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
411 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {
412 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);
413 if (reg < 0)
414 return reg;
415 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,
416 BCM54612E_LED4_CLK125OUT_EN | reg);
417 if (err < 0)
418 return err;
419 }
420
421 /* With BCM54811, BroadR-Reach implies no autoneg */
422 if (priv->brr_mode)
423 phydev->autoneg = 0;
424
425 /* Enable MII Lite (No TXER, RXER, CRS, COL) if configured */
426 if (phydev->interface == PHY_INTERFACE_MODE_MIILITE)
427 exp_sync_ethernet = BCM_EXP_SYNC_ETHERNET_MII_LITE;
428 else
429 exp_sync_ethernet = 0;
430
431 err = bcm_phy_modify_exp(phydev, BCM_EXP_SYNC_ETHERNET,
432 BCM_EXP_SYNC_ETHERNET_MII_LITE,
433 exp_sync_ethernet);
434 if (err < 0)
435 return err;
436
437 /* Enable RGMII if configured */
438 if (phy_interface_is_rgmii(phydev))
439 aux_rgmii_en = MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN |
440 MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
441 else
442 aux_rgmii_en = 0;
443
444 /* Also writing Reserved bits 6:5 because the documentation requires
445 * them to be written to 0b11
446 */
447 err = bcm54xx_auxctl_write(phydev,
448 MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
449 MII_BCM54XX_AUXCTL_MISC_WREN |
450 aux_rgmii_en |
451 MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RSVD);
452 if (err < 0)
453 return err;
454
455 return bcm5481x_set_brrmode(phydev, priv->brr_mode);
456 }
457
bcm54xx_config_init(struct phy_device * phydev)458 static int bcm54xx_config_init(struct phy_device *phydev)
459 {
460 int reg, err, val;
461
462 reg = phy_read(phydev, MII_BCM54XX_ECR);
463 if (reg < 0)
464 return reg;
465
466 /* Mask interrupts globally. */
467 reg |= MII_BCM54XX_ECR_IM;
468 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
469 if (err < 0)
470 return err;
471
472 /* Unmask events we are interested in. */
473 reg = ~(MII_BCM54XX_INT_DUPLEX |
474 MII_BCM54XX_INT_SPEED |
475 MII_BCM54XX_INT_LINK);
476 err = phy_write(phydev, MII_BCM54XX_IMR, reg);
477 if (err < 0)
478 return err;
479
480 if ((phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) ||
481 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M)) &&
482 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
483 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
484
485 bcm54xx_adjust_rxrefclk(phydev);
486
487 switch (phydev->drv->phy_id & PHY_ID_MATCH_MODEL_MASK) {
488 case PHY_ID_BCM50610:
489 case PHY_ID_BCM50610M:
490 err = bcm54xx_config_clock_delay(phydev);
491 break;
492 case PHY_ID_BCM54210E:
493 err = bcm54210e_config_init(phydev);
494 break;
495 case PHY_ID_BCM54612E:
496 err = bcm54612e_config_init(phydev);
497 break;
498 case PHY_ID_BCM54616S:
499 err = bcm54616s_config_init(phydev);
500 break;
501 case PHY_ID_BCM54810:
502 /* For BCM54810, we need to disable BroadR-Reach function */
503 val = bcm_phy_read_exp(phydev,
504 BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
505 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
506 err = bcm_phy_write_exp(phydev,
507 BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
508 val);
509 break;
510 case PHY_ID_BCM54811:
511 err = bcm54811_config_init(phydev);
512 break;
513 }
514 if (err)
515 return err;
516
517 bcm54xx_phydsp_config(phydev);
518
519 /* For non-SFP setups, encode link speed into LED1 and LED3 pair
520 * (green/amber).
521 * Also flash these two LEDs on activity. This means configuring
522 * them for MULTICOLOR and encoding link/activity into them.
523 * Don't do this for devices on an SFP module, since some of these
524 * use the LED outputs to control the SFP LOS signal, and changing
525 * these settings will cause LOS to malfunction.
526 */
527 if (!phy_on_sfp(phydev)) {
528 val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
529 BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
530 bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val);
531
532 val = BCM_LED_MULTICOLOR_IN_PHASE |
533 BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
534 BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
535 bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
536 }
537
538 bcm54xx_ptp_config_init(phydev);
539
540 /* Acknowledge any left over interrupt and charge the device for
541 * wake-up.
542 */
543 err = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
544 if (err < 0)
545 return err;
546
547 if (err)
548 pm_wakeup_event(&phydev->mdio.dev, 0);
549
550 return 0;
551 }
552
bcm54xx_iddq_set(struct phy_device * phydev,bool enable)553 static int bcm54xx_iddq_set(struct phy_device *phydev, bool enable)
554 {
555 int ret = 0;
556
557 if (!(phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND))
558 return ret;
559
560 ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_IDDQ_CTRL);
561 if (ret < 0)
562 goto out;
563
564 if (enable)
565 ret |= BCM54XX_TOP_MISC_IDDQ_SR | BCM54XX_TOP_MISC_IDDQ_LP;
566 else
567 ret &= ~(BCM54XX_TOP_MISC_IDDQ_SR | BCM54XX_TOP_MISC_IDDQ_LP);
568
569 ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_IDDQ_CTRL, ret);
570 out:
571 return ret;
572 }
573
bcm54xx_set_wakeup_irq(struct phy_device * phydev,bool state)574 static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state)
575 {
576 struct bcm54xx_phy_priv *priv = phydev->priv;
577 int ret = 0;
578
579 if (!bcm54xx_phy_can_wakeup(phydev))
580 return ret;
581
582 if (priv->wake_irq_enabled != state) {
583 if (state)
584 ret = enable_irq_wake(priv->wake_irq);
585 else
586 ret = disable_irq_wake(priv->wake_irq);
587 priv->wake_irq_enabled = state;
588 }
589
590 return ret;
591 }
592
bcm54xx_suspend(struct phy_device * phydev)593 static int bcm54xx_suspend(struct phy_device *phydev)
594 {
595 struct bcm54xx_phy_priv *priv = phydev->priv;
596 int ret = 0;
597
598 mutex_lock(&phydev->lock);
599 bcm_phy_update_stats_shadow(phydev, priv->stats);
600 mutex_unlock(&phydev->lock);
601
602 bcm54xx_ptp_stop(phydev);
603
604 /* Acknowledge any Wake-on-LAN interrupt prior to suspend */
605 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
606 if (ret < 0)
607 return ret;
608
609 if (phydev->wol_enabled)
610 return bcm54xx_set_wakeup_irq(phydev, true);
611
612 /* We cannot use a read/modify/write here otherwise the PHY gets into
613 * a bad state where its LEDs keep flashing, thus defeating the purpose
614 * of low power mode.
615 */
616 ret = phy_write(phydev, MII_BMCR, BMCR_PDOWN);
617 if (ret < 0)
618 return ret;
619
620 return bcm54xx_iddq_set(phydev, true);
621 }
622
bcm54xx_resume(struct phy_device * phydev)623 static int bcm54xx_resume(struct phy_device *phydev)
624 {
625 int ret = 0;
626
627 if (phydev->wol_enabled) {
628 ret = bcm54xx_set_wakeup_irq(phydev, false);
629 if (ret)
630 return ret;
631 }
632
633 ret = bcm54xx_iddq_set(phydev, false);
634 if (ret < 0)
635 return ret;
636
637 /* Writes to register other than BMCR would be ignored
638 * unless we clear the PDOWN bit first
639 */
640 ret = genphy_resume(phydev);
641 if (ret < 0)
642 return ret;
643
644 /* Upon exiting power down, the PHY remains in an internal reset state
645 * for 40us
646 */
647 fsleep(40);
648
649 /* Issue a soft reset after clearing the power down bit
650 * and before doing any other configuration.
651 */
652 if (phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND) {
653 ret = genphy_soft_reset(phydev);
654 if (ret < 0)
655 return ret;
656 }
657
658 return bcm54xx_config_init(phydev);
659 }
660
bcm54810_read_mmd(struct phy_device * phydev,int devnum,u16 regnum)661 static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
662 {
663 return -EOPNOTSUPP;
664 }
665
bcm54810_write_mmd(struct phy_device * phydev,int devnum,u16 regnum,u16 val)666 static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
667 u16 val)
668 {
669 return -EOPNOTSUPP;
670 }
671
672
673 /**
674 * bcm5481x_read_abilities - read PHY abilities from LRESR or Clause 22
675 * (BMSR) registers, based on whether the PHY is in BroadR-Reach or IEEE mode
676 * @phydev: target phy_device struct
677 *
678 * Description: Reads the PHY's abilities and populates phydev->supported
679 * accordingly. The register to read the abilities from is determined by
680 * the brr mode setting of the PHY as read from the device tree.
681 * Note that the LRE and IEEE sets of abilities are disjunct, in other words,
682 * not only the link modes differ, but also the auto-negotiation and
683 * master-slave setup is controlled differently.
684 *
685 * Returns: 0 on success, < 0 on failure
686 */
bcm5481x_read_abilities(struct phy_device * phydev)687 static int bcm5481x_read_abilities(struct phy_device *phydev)
688 {
689 struct device_node *np = phydev->mdio.dev.of_node;
690 struct bcm54xx_phy_priv *priv = phydev->priv;
691 int i, val, err, aneg;
692
693 for (i = 0; i < ARRAY_SIZE(bcm54811_linkmodes); i++)
694 linkmode_clear_bit(bcm54811_linkmodes[i], phydev->supported);
695
696 priv->brr_mode = of_property_read_bool(np, "brr-mode");
697
698 /* Set BroadR-Reach mode as configured in the DT. */
699 err = bcm5481x_set_brrmode(phydev, priv->brr_mode);
700 if (err)
701 return err;
702
703 if (priv->brr_mode) {
704 linkmode_set_bit_array(phy_basic_ports_array,
705 ARRAY_SIZE(phy_basic_ports_array),
706 phydev->supported);
707
708 val = phy_read(phydev, MII_BCM54XX_LRESR);
709 if (val < 0)
710 return val;
711
712 /* BCM54811 is not capable of LDS but the corresponding bit
713 * in LRESR is set to 1 and marked "Ignore" in the datasheet.
714 * So we must read the bcm54811 as unable to auto-negotiate
715 * in BroadR-Reach mode.
716 */
717 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811))
718 aneg = 0;
719 else
720 aneg = val & LRESR_LDSABILITY;
721
722 linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
723 phydev->supported,
724 aneg);
725 linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
726 phydev->supported,
727 val & LRESR_100_1PAIR);
728 linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,
729 phydev->supported,
730 val & LRESR_10_1PAIR);
731 return 0;
732 }
733
734 return genphy_read_abilities(phydev);
735 }
736
bcm5481x_config_delay_swap(struct phy_device * phydev)737 static int bcm5481x_config_delay_swap(struct phy_device *phydev)
738 {
739 struct device_node *np = phydev->mdio.dev.of_node;
740
741 /* Set up the delay. */
742 bcm54xx_config_clock_delay(phydev);
743
744 if (of_property_read_bool(np, "enet-phy-lane-swap")) {
745 /* Lane Swap - Undocumented register...magic! */
746 int ret = bcm_phy_write_exp(phydev,
747 MII_BCM54XX_EXP_SEL_ER + 0x9,
748 0x11B);
749 if (ret < 0)
750 return ret;
751 }
752
753 return 0;
754 }
755
bcm5481_config_aneg(struct phy_device * phydev)756 static int bcm5481_config_aneg(struct phy_device *phydev)
757 {
758 struct bcm54xx_phy_priv *priv = phydev->priv;
759 int ret;
760
761 /* Aneg firstly. */
762 if (priv->brr_mode)
763 ret = bcm_config_lre_aneg(phydev, false);
764 else
765 ret = genphy_config_aneg(phydev);
766
767 if (ret)
768 return ret;
769
770 /* Then we can set up the delay and swap. */
771 return bcm5481x_config_delay_swap(phydev);
772 }
773
bcm54811_config_aneg(struct phy_device * phydev)774 static int bcm54811_config_aneg(struct phy_device *phydev)
775 {
776 struct bcm54xx_phy_priv *priv = phydev->priv;
777 int ret;
778
779 /* Aneg firstly. */
780 if (priv->brr_mode) {
781 /* BCM54811 is only capable of autonegotiation in IEEE mode.
782 * In BroadR-Reach mode, disable the Long Distance Signaling,
783 * the BRR mode autoneg as supported in other Broadcom PHYs.
784 * This bit is marked as "Reserved" and "Default 1, must be
785 * written to 0 after every device reset" in the datasheet.
786 */
787 ret = phy_modify(phydev, MII_BCM54XX_LRECR, LRECR_LDSEN, 0);
788 if (ret < 0)
789 return ret;
790 ret = bcm_config_lre_aneg(phydev, false);
791 } else {
792 ret = genphy_config_aneg(phydev);
793 }
794
795 if (ret)
796 return ret;
797
798 /* Then we can set up the delay and swap. */
799 return bcm5481x_config_delay_swap(phydev);
800 }
801
802 struct bcm54616s_phy_priv {
803 bool mode_1000bx_en;
804 };
805
bcm54616s_probe(struct phy_device * phydev)806 static int bcm54616s_probe(struct phy_device *phydev)
807 {
808 struct bcm54616s_phy_priv *priv;
809 int val;
810
811 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
812 if (!priv)
813 return -ENOMEM;
814
815 phydev->priv = priv;
816
817 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
818 if (val < 0)
819 return val;
820
821 /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0]
822 * is 01b, and the link between PHY and its link partner can be
823 * either 1000Base-X or 100Base-FX.
824 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX
825 * support is still missing as of now.
826 */
827 if ((val & BCM54XX_SHD_INTF_SEL_MASK) == BCM54XX_SHD_INTF_SEL_RGMII) {
828 val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
829 if (val < 0)
830 return val;
831
832 /* Bit 0 of the SerDes 100-FX Control register, when set
833 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
834 * When this bit is set to 0, it sets the GMII/RGMII ->
835 * 1000BASE-X configuration.
836 */
837 if (!(val & BCM54616S_100FX_MODE))
838 priv->mode_1000bx_en = true;
839
840 phydev->port = PORT_FIBRE;
841 }
842
843 return 0;
844 }
845
bcm54616s_config_aneg(struct phy_device * phydev)846 static int bcm54616s_config_aneg(struct phy_device *phydev)
847 {
848 struct bcm54616s_phy_priv *priv = phydev->priv;
849 int ret;
850
851 /* Aneg firstly. */
852 if (priv->mode_1000bx_en)
853 ret = genphy_c37_config_aneg(phydev);
854 else
855 ret = genphy_config_aneg(phydev);
856
857 /* Then we can set up the delay. */
858 bcm54xx_config_clock_delay(phydev);
859
860 return ret;
861 }
862
bcm54616s_read_status(struct phy_device * phydev)863 static int bcm54616s_read_status(struct phy_device *phydev)
864 {
865 struct bcm54616s_phy_priv *priv = phydev->priv;
866 bool changed;
867 int err;
868
869 if (priv->mode_1000bx_en)
870 err = genphy_c37_read_status(phydev, &changed);
871 else
872 err = genphy_read_status(phydev);
873
874 return err;
875 }
876
brcm_fet_config_init(struct phy_device * phydev)877 static int brcm_fet_config_init(struct phy_device *phydev)
878 {
879 int reg, err, err2, brcmtest;
880
881 /* Reset the PHY to bring it to a known state. */
882 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
883 if (err < 0)
884 return err;
885
886 /* The datasheet indicates the PHY needs up to 1us to complete a reset,
887 * build some slack here.
888 */
889 usleep_range(1000, 2000);
890
891 /* The PHY requires 65 MDC clock cycles to complete a write operation
892 * and turnaround the line properly.
893 *
894 * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac)
895 * may flag the lack of turn-around as a read failure. This is
896 * particularly true with this combination since the MDIO controller
897 * only used 64 MDC cycles. This is not a critical failure in this
898 * specific case and it has no functional impact otherwise, so we let
899 * that one go through. If there is a genuine bus error, the next read
900 * of MII_BRCM_FET_INTREG will error out.
901 */
902 err = phy_read(phydev, MII_BMCR);
903 if (err < 0 && err != -EIO)
904 return err;
905
906 /* Read to clear status bits */
907 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
908 if (reg < 0)
909 return reg;
910
911 /* Unmask events we are interested in and mask interrupts globally. */
912 if (phydev->drv->phy_id == PHY_ID_BCM5221)
913 reg = MII_BRCM_FET_IR_ENABLE |
914 MII_BRCM_FET_IR_MASK;
915 else
916 reg = MII_BRCM_FET_IR_DUPLEX_EN |
917 MII_BRCM_FET_IR_SPEED_EN |
918 MII_BRCM_FET_IR_LINK_EN |
919 MII_BRCM_FET_IR_ENABLE |
920 MII_BRCM_FET_IR_MASK;
921
922 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
923 if (err < 0)
924 return err;
925
926 /* Enable shadow register access */
927 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
928 if (brcmtest < 0)
929 return brcmtest;
930
931 reg = brcmtest | MII_BRCM_FET_BT_SRE;
932
933 phy_lock_mdio_bus(phydev);
934
935 err = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
936 if (err < 0) {
937 phy_unlock_mdio_bus(phydev);
938 return err;
939 }
940
941 if (phydev->drv->phy_id != PHY_ID_BCM5221) {
942 /* Set the LED mode */
943 reg = __phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
944 if (reg < 0) {
945 err = reg;
946 goto done;
947 }
948
949 err = __phy_modify(phydev, MII_BRCM_FET_SHDW_AUXMODE4,
950 MII_BRCM_FET_SHDW_AM4_LED_MASK,
951 MII_BRCM_FET_SHDW_AM4_LED_MODE1);
952 if (err < 0)
953 goto done;
954
955 /* Enable auto MDIX */
956 err = __phy_set_bits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
957 MII_BRCM_FET_SHDW_MC_FAME);
958 if (err < 0)
959 goto done;
960 }
961
962 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
963 /* Enable auto power down */
964 err = __phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
965 MII_BRCM_FET_SHDW_AS2_APDE);
966 }
967
968 done:
969 /* Disable shadow register access */
970 err2 = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
971 if (!err)
972 err = err2;
973
974 phy_unlock_mdio_bus(phydev);
975
976 return err;
977 }
978
brcm_fet_ack_interrupt(struct phy_device * phydev)979 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
980 {
981 int reg;
982
983 /* Clear pending interrupts. */
984 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
985 if (reg < 0)
986 return reg;
987
988 return 0;
989 }
990
brcm_fet_config_intr(struct phy_device * phydev)991 static int brcm_fet_config_intr(struct phy_device *phydev)
992 {
993 int reg, err;
994
995 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
996 if (reg < 0)
997 return reg;
998
999 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
1000 err = brcm_fet_ack_interrupt(phydev);
1001 if (err)
1002 return err;
1003
1004 reg &= ~MII_BRCM_FET_IR_MASK;
1005 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
1006 } else {
1007 reg |= MII_BRCM_FET_IR_MASK;
1008 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
1009 if (err)
1010 return err;
1011
1012 err = brcm_fet_ack_interrupt(phydev);
1013 }
1014
1015 return err;
1016 }
1017
brcm_fet_handle_interrupt(struct phy_device * phydev)1018 static irqreturn_t brcm_fet_handle_interrupt(struct phy_device *phydev)
1019 {
1020 int irq_status;
1021
1022 irq_status = phy_read(phydev, MII_BRCM_FET_INTREG);
1023 if (irq_status < 0) {
1024 phy_error(phydev);
1025 return IRQ_NONE;
1026 }
1027
1028 if (irq_status == 0)
1029 return IRQ_NONE;
1030
1031 phy_trigger_machine(phydev);
1032
1033 return IRQ_HANDLED;
1034 }
1035
brcm_fet_suspend(struct phy_device * phydev)1036 static int brcm_fet_suspend(struct phy_device *phydev)
1037 {
1038 int reg, err, err2, brcmtest;
1039
1040 /* We cannot use a read/modify/write here otherwise the PHY continues
1041 * to drive LEDs which defeats the purpose of low power mode.
1042 */
1043 err = phy_write(phydev, MII_BMCR, BMCR_PDOWN);
1044 if (err < 0)
1045 return err;
1046
1047 /* Enable shadow register access */
1048 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
1049 if (brcmtest < 0)
1050 return brcmtest;
1051
1052 reg = brcmtest | MII_BRCM_FET_BT_SRE;
1053
1054 phy_lock_mdio_bus(phydev);
1055
1056 err = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
1057 if (err < 0) {
1058 phy_unlock_mdio_bus(phydev);
1059 return err;
1060 }
1061
1062 if (phydev->drv->phy_id == PHY_ID_BCM5221)
1063 /* Force Low Power Mode with clock enabled */
1064 reg = BCM5221_SHDW_AM4_EN_CLK_LPM | BCM5221_SHDW_AM4_FORCE_LPM;
1065 else
1066 /* Set standby mode */
1067 reg = MII_BRCM_FET_SHDW_AM4_STANDBY;
1068
1069 err = __phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
1070
1071 /* Disable shadow register access */
1072 err2 = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
1073 if (!err)
1074 err = err2;
1075
1076 phy_unlock_mdio_bus(phydev);
1077
1078 return err;
1079 }
1080
bcm5221_config_aneg(struct phy_device * phydev)1081 static int bcm5221_config_aneg(struct phy_device *phydev)
1082 {
1083 int ret, val;
1084
1085 ret = genphy_config_aneg(phydev);
1086 if (ret)
1087 return ret;
1088
1089 switch (phydev->mdix_ctrl) {
1090 case ETH_TP_MDI:
1091 val = BCM5221_AEGSR_MDIX_DIS;
1092 break;
1093 case ETH_TP_MDI_X:
1094 val = BCM5221_AEGSR_MDIX_DIS | BCM5221_AEGSR_MDIX_MAN_SWAP;
1095 break;
1096 case ETH_TP_MDI_AUTO:
1097 val = 0;
1098 break;
1099 default:
1100 return 0;
1101 }
1102
1103 return phy_modify(phydev, BCM5221_AEGSR, BCM5221_AEGSR_MDIX_MAN_SWAP |
1104 BCM5221_AEGSR_MDIX_DIS,
1105 val);
1106 }
1107
bcm5221_read_status(struct phy_device * phydev)1108 static int bcm5221_read_status(struct phy_device *phydev)
1109 {
1110 int ret;
1111
1112 /* Read MDIX status */
1113 ret = phy_read(phydev, BCM5221_AEGSR);
1114 if (ret < 0)
1115 return ret;
1116
1117 if (ret & BCM5221_AEGSR_MDIX_DIS) {
1118 if (ret & BCM5221_AEGSR_MDIX_MAN_SWAP)
1119 phydev->mdix_ctrl = ETH_TP_MDI_X;
1120 else
1121 phydev->mdix_ctrl = ETH_TP_MDI;
1122 } else {
1123 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
1124 }
1125
1126 if (ret & BCM5221_AEGSR_MDIX_STATUS)
1127 phydev->mdix = ETH_TP_MDI_X;
1128 else
1129 phydev->mdix = ETH_TP_MDI;
1130
1131 return genphy_read_status(phydev);
1132 }
1133
bcm54xx_phy_get_wol(struct phy_device * phydev,struct ethtool_wolinfo * wol)1134 static void bcm54xx_phy_get_wol(struct phy_device *phydev,
1135 struct ethtool_wolinfo *wol)
1136 {
1137 /* We cannot wake-up if we do not have a dedicated PHY interrupt line
1138 * or an out of band GPIO descriptor for wake-up. Zeroing
1139 * wol->supported allows the caller (MAC driver) to play through and
1140 * offer its own Wake-on-LAN scheme if available.
1141 */
1142 if (!bcm54xx_phy_can_wakeup(phydev)) {
1143 wol->supported = 0;
1144 return;
1145 }
1146
1147 bcm_phy_get_wol(phydev, wol);
1148 }
1149
bcm54xx_phy_set_wol(struct phy_device * phydev,struct ethtool_wolinfo * wol)1150 static int bcm54xx_phy_set_wol(struct phy_device *phydev,
1151 struct ethtool_wolinfo *wol)
1152 {
1153 int ret;
1154
1155 /* We cannot wake-up if we do not have a dedicated PHY interrupt line
1156 * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP
1157 * allows the caller (MAC driver) to play through and offer its own
1158 * Wake-on-LAN scheme if available.
1159 */
1160 if (!bcm54xx_phy_can_wakeup(phydev))
1161 return -EOPNOTSUPP;
1162
1163 ret = bcm_phy_set_wol(phydev, wol);
1164 if (ret < 0)
1165 return ret;
1166
1167 return 0;
1168 }
1169
bcm54xx_phy_probe(struct phy_device * phydev)1170 static int bcm54xx_phy_probe(struct phy_device *phydev)
1171 {
1172 struct bcm54xx_phy_priv *priv;
1173 struct gpio_desc *wakeup_gpio;
1174 int ret = 0;
1175
1176 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
1177 if (!priv)
1178 return -ENOMEM;
1179
1180 priv->wake_irq = -ENXIO;
1181
1182 phydev->priv = priv;
1183
1184 priv->stats = devm_kcalloc(&phydev->mdio.dev,
1185 bcm_phy_get_sset_count(phydev), sizeof(u64),
1186 GFP_KERNEL);
1187 if (!priv->stats)
1188 return -ENOMEM;
1189
1190 priv->ptp = bcm_ptp_probe(phydev);
1191 if (IS_ERR(priv->ptp))
1192 return PTR_ERR(priv->ptp);
1193
1194 /* We cannot utilize the _optional variant here since we want to know
1195 * whether the GPIO descriptor exists or not to advertise Wake-on-LAN
1196 * support or not.
1197 */
1198 wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN);
1199 if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER)
1200 return PTR_ERR(wakeup_gpio);
1201
1202 if (!IS_ERR(wakeup_gpio)) {
1203 priv->wake_irq = gpiod_to_irq(wakeup_gpio);
1204
1205 /* Dummy interrupt handler which is not enabled but is provided
1206 * in order for the interrupt descriptor to be fully set-up.
1207 */
1208 ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq,
1209 bcm_phy_wol_isr,
1210 IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,
1211 dev_name(&phydev->mdio.dev), phydev);
1212 if (ret)
1213 return ret;
1214 }
1215
1216 /* If we do not have a main interrupt or a side-band wake-up interrupt,
1217 * then the device cannot be marked as wake-up capable.
1218 */
1219 if (!bcm54xx_phy_can_wakeup(phydev))
1220 return 0;
1221
1222 return device_init_wakeup(&phydev->mdio.dev, true);
1223 }
1224
bcm54xx_get_stats(struct phy_device * phydev,struct ethtool_stats * stats,u64 * data)1225 static void bcm54xx_get_stats(struct phy_device *phydev,
1226 struct ethtool_stats *stats, u64 *data)
1227 {
1228 struct bcm54xx_phy_priv *priv = phydev->priv;
1229
1230 bcm_phy_get_stats(phydev, priv->stats, stats, data);
1231 }
1232
bcm54xx_link_change_notify(struct phy_device * phydev)1233 static void bcm54xx_link_change_notify(struct phy_device *phydev)
1234 {
1235 u16 mask = MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE |
1236 MII_BCM54XX_EXP_EXP08_FORCE_DAC_WAKE;
1237 int ret;
1238
1239 if (phydev->state != PHY_RUNNING)
1240 return;
1241
1242 /* Don't change the DAC wake settings if auto power down
1243 * is not requested.
1244 */
1245 if (!(phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
1246 return;
1247
1248 ret = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP08);
1249 if (ret < 0)
1250 return;
1251
1252 /* Enable/disable 10BaseT auto and forced early DAC wake depending
1253 * on the negotiated speed, those settings should only be done
1254 * for 10Mbits/sec.
1255 */
1256 if (phydev->speed == SPEED_10)
1257 ret |= mask;
1258 else
1259 ret &= ~mask;
1260 bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, ret);
1261 }
1262
lre_read_master_slave(struct phy_device * phydev)1263 static int lre_read_master_slave(struct phy_device *phydev)
1264 {
1265 int cfg = MASTER_SLAVE_CFG_UNKNOWN, state;
1266 int val;
1267
1268 /* In BroadR-Reach mode we are always capable of master-slave
1269 * and there is no preferred master or slave configuration
1270 */
1271 phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN;
1272 phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
1273
1274 val = phy_read(phydev, MII_BCM54XX_LRECR);
1275 if (val < 0)
1276 return val;
1277
1278 if ((val & LRECR_LDSEN) == 0) {
1279 if (val & LRECR_MASTER)
1280 cfg = MASTER_SLAVE_CFG_MASTER_FORCE;
1281 else
1282 cfg = MASTER_SLAVE_CFG_SLAVE_FORCE;
1283 }
1284
1285 val = phy_read(phydev, MII_BCM54XX_LRELDSE);
1286 if (val < 0)
1287 return val;
1288
1289 if (val & LDSE_MASTER)
1290 state = MASTER_SLAVE_STATE_MASTER;
1291 else
1292 state = MASTER_SLAVE_STATE_SLAVE;
1293
1294 phydev->master_slave_get = cfg;
1295 phydev->master_slave_state = state;
1296
1297 return 0;
1298 }
1299
1300 /* Read LDS Link Partner Ability in BroadR-Reach mode */
lre_read_lpa(struct phy_device * phydev)1301 static int lre_read_lpa(struct phy_device *phydev)
1302 {
1303 int i, lrelpa;
1304
1305 if (phydev->autoneg != AUTONEG_ENABLE) {
1306 if (!phydev->autoneg_complete) {
1307 /* aneg not yet done, reset all relevant bits */
1308 for (i = 0; i < ARRAY_SIZE(lds_br_bits); i++)
1309 linkmode_clear_bit(lds_br_bits[i],
1310 phydev->lp_advertising);
1311
1312 return 0;
1313 }
1314
1315 /* Long-Distance Signaling Link Partner Ability */
1316 lrelpa = phy_read(phydev, MII_BCM54XX_LRELPA);
1317 if (lrelpa < 0)
1318 return lrelpa;
1319
1320 linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
1321 phydev->lp_advertising,
1322 lrelpa & LRELPA_PAUSE_ASYM);
1323 linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,
1324 phydev->lp_advertising,
1325 lrelpa & LRELPA_PAUSE);
1326 linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
1327 phydev->lp_advertising,
1328 lrelpa & LRELPA_100_1PAIR);
1329 linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,
1330 phydev->lp_advertising,
1331 lrelpa & LRELPA_10_1PAIR);
1332 } else {
1333 linkmode_zero(phydev->lp_advertising);
1334 }
1335
1336 return 0;
1337 }
1338
lre_read_status_fixed(struct phy_device * phydev)1339 static int lre_read_status_fixed(struct phy_device *phydev)
1340 {
1341 int lrecr = phy_read(phydev, MII_BCM54XX_LRECR);
1342
1343 if (lrecr < 0)
1344 return lrecr;
1345
1346 phydev->duplex = DUPLEX_FULL;
1347
1348 if (lrecr & LRECR_SPEED100)
1349 phydev->speed = SPEED_100;
1350 else
1351 phydev->speed = SPEED_10;
1352
1353 return 0;
1354 }
1355
1356 /**
1357 * lre_update_link - update link status in @phydev
1358 * @phydev: target phy_device struct
1359 * Return: 0 on success, < 0 on error
1360 *
1361 * Description: Update the value in phydev->link to reflect the
1362 * current link value. In order to do this, we need to read
1363 * the status register twice, keeping the second value.
1364 * This is a genphy_update_link modified to work on LRE registers
1365 * of BroadR-Reach PHY
1366 */
lre_update_link(struct phy_device * phydev)1367 static int lre_update_link(struct phy_device *phydev)
1368 {
1369 int status = 0, lrecr;
1370
1371 lrecr = phy_read(phydev, MII_BCM54XX_LRECR);
1372 if (lrecr < 0)
1373 return lrecr;
1374
1375 /* Autoneg is being started, therefore disregard BMSR value and
1376 * report link as down.
1377 */
1378 if (lrecr & BMCR_ANRESTART)
1379 goto done;
1380
1381 /* The link state is latched low so that momentary link
1382 * drops can be detected. Do not double-read the status
1383 * in polling mode to detect such short link drops except
1384 * the link was already down.
1385 */
1386 if (!phy_polling_mode(phydev) || !phydev->link) {
1387 status = phy_read(phydev, MII_BCM54XX_LRESR);
1388 if (status < 0)
1389 return status;
1390 else if (status & LRESR_LSTATUS)
1391 goto done;
1392 }
1393
1394 /* Read link and autonegotiation status */
1395 status = phy_read(phydev, MII_BCM54XX_LRESR);
1396 if (status < 0)
1397 return status;
1398 done:
1399 phydev->link = status & LRESR_LSTATUS ? 1 : 0;
1400 phydev->autoneg_complete = status & LRESR_LDSCOMPLETE ? 1 : 0;
1401
1402 /* Consider the case that autoneg was started and "aneg complete"
1403 * bit has been reset, but "link up" bit not yet.
1404 */
1405 if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
1406 phydev->link = 0;
1407
1408 return 0;
1409 }
1410
1411 /* Get the status in BroadRReach mode just like genphy_read_status does
1412 * in normal mode
1413 */
bcm54811_lre_read_status(struct phy_device * phydev)1414 static int bcm54811_lre_read_status(struct phy_device *phydev)
1415 {
1416 int err, old_link = phydev->link;
1417
1418 /* Update the link, but return if there was an error */
1419 err = lre_update_link(phydev);
1420 if (err)
1421 return err;
1422
1423 /* why bother the PHY if nothing can have changed */
1424 if (phydev->autoneg ==
1425 AUTONEG_ENABLE && old_link && phydev->link)
1426 return 0;
1427
1428 phydev->speed = SPEED_UNKNOWN;
1429 phydev->duplex = DUPLEX_UNKNOWN;
1430 phydev->pause = 0;
1431 phydev->asym_pause = 0;
1432
1433 err = lre_read_master_slave(phydev);
1434 if (err < 0)
1435 return err;
1436
1437 /* Read LDS Link Partner Ability */
1438 err = lre_read_lpa(phydev);
1439 if (err < 0)
1440 return err;
1441
1442 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
1443 phy_resolve_aneg_linkmode(phydev);
1444 else if (phydev->autoneg == AUTONEG_DISABLE)
1445 err = lre_read_status_fixed(phydev);
1446
1447 return err;
1448 }
1449
bcm54811_read_status(struct phy_device * phydev)1450 static int bcm54811_read_status(struct phy_device *phydev)
1451 {
1452 struct bcm54xx_phy_priv *priv = phydev->priv;
1453
1454 if (priv->brr_mode)
1455 return bcm54811_lre_read_status(phydev);
1456
1457 return genphy_read_status(phydev);
1458 }
1459
bcm54xx_disable_autonomous_eee(struct phy_device * phydev)1460 static int bcm54xx_disable_autonomous_eee(struct phy_device *phydev)
1461 {
1462 return bcm_phy_modify_exp(phydev, BCM54XX_TOP_MISC_MII_BUF_CNTL0,
1463 BCM54XX_MII_BUF_CNTL0_AUTOGREEEN_EN, 0);
1464 }
1465
1466 static struct phy_driver broadcom_drivers[] = {
1467 {
1468 PHY_ID_MATCH_MODEL(PHY_ID_BCM5411),
1469 .name = "Broadcom BCM5411",
1470 /* PHY_GBIT_FEATURES */
1471 .get_sset_count = bcm_phy_get_sset_count,
1472 .get_strings = bcm_phy_get_strings,
1473 .get_stats = bcm54xx_get_stats,
1474 .probe = bcm54xx_phy_probe,
1475 .config_init = bcm54xx_config_init,
1476 .config_intr = bcm_phy_config_intr,
1477 .handle_interrupt = bcm_phy_handle_interrupt,
1478 .link_change_notify = bcm54xx_link_change_notify,
1479 }, {
1480 PHY_ID_MATCH_MODEL(PHY_ID_BCM5421),
1481 .name = "Broadcom BCM5421",
1482 /* PHY_GBIT_FEATURES */
1483 .get_sset_count = bcm_phy_get_sset_count,
1484 .get_strings = bcm_phy_get_strings,
1485 .get_stats = bcm54xx_get_stats,
1486 .probe = bcm54xx_phy_probe,
1487 .config_init = bcm54xx_config_init,
1488 .config_intr = bcm_phy_config_intr,
1489 .handle_interrupt = bcm_phy_handle_interrupt,
1490 .link_change_notify = bcm54xx_link_change_notify,
1491 }, {
1492 PHY_ID_MATCH_MODEL(PHY_ID_BCM54210E),
1493 .name = "Broadcom BCM54210E",
1494 /* PHY_GBIT_FEATURES */
1495 .flags = PHY_ALWAYS_CALL_SUSPEND,
1496 .get_sset_count = bcm_phy_get_sset_count,
1497 .get_strings = bcm_phy_get_strings,
1498 .get_stats = bcm54xx_get_stats,
1499 .probe = bcm54xx_phy_probe,
1500 .config_init = bcm54xx_config_init,
1501 .config_intr = bcm_phy_config_intr,
1502 .handle_interrupt = bcm_phy_handle_interrupt,
1503 .link_change_notify = bcm54xx_link_change_notify,
1504 .suspend = bcm54xx_suspend,
1505 .resume = bcm54xx_resume,
1506 .get_wol = bcm54xx_phy_get_wol,
1507 .set_wol = bcm54xx_phy_set_wol,
1508 .led_brightness_set = bcm_phy_led_brightness_set,
1509 .disable_autonomous_eee = bcm54xx_disable_autonomous_eee,
1510 }, {
1511 PHY_ID_MATCH_MODEL(PHY_ID_BCM5461),
1512 .name = "Broadcom BCM5461",
1513 /* PHY_GBIT_FEATURES */
1514 .get_sset_count = bcm_phy_get_sset_count,
1515 .get_strings = bcm_phy_get_strings,
1516 .get_stats = bcm54xx_get_stats,
1517 .probe = bcm54xx_phy_probe,
1518 .config_init = bcm54xx_config_init,
1519 .config_intr = bcm_phy_config_intr,
1520 .handle_interrupt = bcm_phy_handle_interrupt,
1521 .link_change_notify = bcm54xx_link_change_notify,
1522 .led_brightness_set = bcm_phy_led_brightness_set,
1523 }, {
1524 PHY_ID_MATCH_MODEL(PHY_ID_BCM54612E),
1525 .name = "Broadcom BCM54612E",
1526 /* PHY_GBIT_FEATURES */
1527 .get_sset_count = bcm_phy_get_sset_count,
1528 .get_strings = bcm_phy_get_strings,
1529 .get_stats = bcm54xx_get_stats,
1530 .probe = bcm54xx_phy_probe,
1531 .config_init = bcm54xx_config_init,
1532 .config_intr = bcm_phy_config_intr,
1533 .handle_interrupt = bcm_phy_handle_interrupt,
1534 .link_change_notify = bcm54xx_link_change_notify,
1535 .led_brightness_set = bcm_phy_led_brightness_set,
1536 .suspend = bcm54xx_suspend,
1537 .resume = bcm54xx_resume,
1538 }, {
1539 PHY_ID_MATCH_MODEL(PHY_ID_BCM54616S),
1540 .name = "Broadcom BCM54616S",
1541 /* PHY_GBIT_FEATURES */
1542 .soft_reset = genphy_soft_reset,
1543 .config_init = bcm54xx_config_init,
1544 .config_aneg = bcm54616s_config_aneg,
1545 .config_intr = bcm_phy_config_intr,
1546 .handle_interrupt = bcm_phy_handle_interrupt,
1547 .read_status = bcm54616s_read_status,
1548 .probe = bcm54616s_probe,
1549 .link_change_notify = bcm54xx_link_change_notify,
1550 .led_brightness_set = bcm_phy_led_brightness_set,
1551 }, {
1552 PHY_ID_MATCH_MODEL(PHY_ID_BCM5464),
1553 .name = "Broadcom BCM5464",
1554 /* PHY_GBIT_FEATURES */
1555 .get_sset_count = bcm_phy_get_sset_count,
1556 .get_strings = bcm_phy_get_strings,
1557 .get_stats = bcm54xx_get_stats,
1558 .probe = bcm54xx_phy_probe,
1559 .config_init = bcm54xx_config_init,
1560 .config_intr = bcm_phy_config_intr,
1561 .handle_interrupt = bcm_phy_handle_interrupt,
1562 .suspend = genphy_suspend,
1563 .resume = genphy_resume,
1564 .link_change_notify = bcm54xx_link_change_notify,
1565 .led_brightness_set = bcm_phy_led_brightness_set,
1566 }, {
1567 PHY_ID_MATCH_MODEL(PHY_ID_BCM5481),
1568 .name = "Broadcom BCM5481",
1569 /* PHY_GBIT_FEATURES */
1570 .get_sset_count = bcm_phy_get_sset_count,
1571 .get_strings = bcm_phy_get_strings,
1572 .get_stats = bcm54xx_get_stats,
1573 .probe = bcm54xx_phy_probe,
1574 .config_init = bcm54xx_config_init,
1575 .config_aneg = bcm5481_config_aneg,
1576 .config_intr = bcm_phy_config_intr,
1577 .handle_interrupt = bcm_phy_handle_interrupt,
1578 .link_change_notify = bcm54xx_link_change_notify,
1579 .led_brightness_set = bcm_phy_led_brightness_set,
1580 }, {
1581 PHY_ID_MATCH_MODEL(PHY_ID_BCM54810),
1582 .name = "Broadcom BCM54810",
1583 /* PHY_GBIT_FEATURES */
1584 .get_sset_count = bcm_phy_get_sset_count,
1585 .get_strings = bcm_phy_get_strings,
1586 .get_stats = bcm54xx_get_stats,
1587 .probe = bcm54xx_phy_probe,
1588 .read_mmd = bcm54810_read_mmd,
1589 .write_mmd = bcm54810_write_mmd,
1590 .config_init = bcm54xx_config_init,
1591 .config_aneg = bcm5481_config_aneg,
1592 .config_intr = bcm_phy_config_intr,
1593 .handle_interrupt = bcm_phy_handle_interrupt,
1594 .suspend = bcm54xx_suspend,
1595 .resume = bcm54xx_resume,
1596 .link_change_notify = bcm54xx_link_change_notify,
1597 .led_brightness_set = bcm_phy_led_brightness_set,
1598 }, {
1599 PHY_ID_MATCH_MODEL(PHY_ID_BCM54811),
1600 .name = "Broadcom BCM54811",
1601 /* PHY_GBIT_FEATURES */
1602 .get_sset_count = bcm_phy_get_sset_count,
1603 .get_strings = bcm_phy_get_strings,
1604 .get_stats = bcm54xx_get_stats,
1605 .probe = bcm54xx_phy_probe,
1606 .config_init = bcm54xx_config_init,
1607 .config_aneg = bcm54811_config_aneg,
1608 .config_intr = bcm_phy_config_intr,
1609 .handle_interrupt = bcm_phy_handle_interrupt,
1610 .read_status = bcm54811_read_status,
1611 .get_features = bcm5481x_read_abilities,
1612 .suspend = bcm54xx_suspend,
1613 .resume = bcm54xx_resume,
1614 .link_change_notify = bcm54xx_link_change_notify,
1615 .led_brightness_set = bcm_phy_led_brightness_set,
1616 }, {
1617 PHY_ID_MATCH_MODEL(PHY_ID_BCM5482),
1618 .name = "Broadcom BCM5482",
1619 /* PHY_GBIT_FEATURES */
1620 .get_sset_count = bcm_phy_get_sset_count,
1621 .get_strings = bcm_phy_get_strings,
1622 .get_stats = bcm54xx_get_stats,
1623 .probe = bcm54xx_phy_probe,
1624 .config_init = bcm54xx_config_init,
1625 .config_intr = bcm_phy_config_intr,
1626 .handle_interrupt = bcm_phy_handle_interrupt,
1627 .link_change_notify = bcm54xx_link_change_notify,
1628 .led_brightness_set = bcm_phy_led_brightness_set,
1629 }, {
1630 PHY_ID_MATCH_MODEL(PHY_ID_BCM50610),
1631 .name = "Broadcom BCM50610",
1632 /* PHY_GBIT_FEATURES */
1633 .get_sset_count = bcm_phy_get_sset_count,
1634 .get_strings = bcm_phy_get_strings,
1635 .get_stats = bcm54xx_get_stats,
1636 .probe = bcm54xx_phy_probe,
1637 .config_init = bcm54xx_config_init,
1638 .config_intr = bcm_phy_config_intr,
1639 .handle_interrupt = bcm_phy_handle_interrupt,
1640 .link_change_notify = bcm54xx_link_change_notify,
1641 .suspend = bcm54xx_suspend,
1642 .resume = bcm54xx_resume,
1643 .led_brightness_set = bcm_phy_led_brightness_set,
1644 }, {
1645 PHY_ID_MATCH_MODEL(PHY_ID_BCM50610M),
1646 .name = "Broadcom BCM50610M",
1647 /* PHY_GBIT_FEATURES */
1648 .get_sset_count = bcm_phy_get_sset_count,
1649 .get_strings = bcm_phy_get_strings,
1650 .get_stats = bcm54xx_get_stats,
1651 .probe = bcm54xx_phy_probe,
1652 .config_init = bcm54xx_config_init,
1653 .config_intr = bcm_phy_config_intr,
1654 .handle_interrupt = bcm_phy_handle_interrupt,
1655 .link_change_notify = bcm54xx_link_change_notify,
1656 .suspend = bcm54xx_suspend,
1657 .resume = bcm54xx_resume,
1658 .led_brightness_set = bcm_phy_led_brightness_set,
1659 }, {
1660 PHY_ID_MATCH_MODEL(PHY_ID_BCM57780),
1661 .name = "Broadcom BCM57780",
1662 /* PHY_GBIT_FEATURES */
1663 .get_sset_count = bcm_phy_get_sset_count,
1664 .get_strings = bcm_phy_get_strings,
1665 .get_stats = bcm54xx_get_stats,
1666 .probe = bcm54xx_phy_probe,
1667 .config_init = bcm54xx_config_init,
1668 .config_intr = bcm_phy_config_intr,
1669 .handle_interrupt = bcm_phy_handle_interrupt,
1670 .link_change_notify = bcm54xx_link_change_notify,
1671 .led_brightness_set = bcm_phy_led_brightness_set,
1672 }, {
1673 PHY_ID_MATCH_MODEL(PHY_ID_BCMAC131),
1674 .name = "Broadcom BCMAC131",
1675 /* PHY_BASIC_FEATURES */
1676 .config_init = brcm_fet_config_init,
1677 .config_intr = brcm_fet_config_intr,
1678 .handle_interrupt = brcm_fet_handle_interrupt,
1679 .suspend = brcm_fet_suspend,
1680 .resume = brcm_fet_config_init,
1681 }, {
1682 PHY_ID_MATCH_MODEL(PHY_ID_BCM5241),
1683 .name = "Broadcom BCM5241",
1684 /* PHY_BASIC_FEATURES */
1685 .config_init = brcm_fet_config_init,
1686 .config_intr = brcm_fet_config_intr,
1687 .handle_interrupt = brcm_fet_handle_interrupt,
1688 .suspend = brcm_fet_suspend,
1689 .resume = brcm_fet_config_init,
1690 }, {
1691 PHY_ID_MATCH_MODEL(PHY_ID_BCM5221),
1692 .name = "Broadcom BCM5221",
1693 /* PHY_BASIC_FEATURES */
1694 .config_init = brcm_fet_config_init,
1695 .config_intr = brcm_fet_config_intr,
1696 .handle_interrupt = brcm_fet_handle_interrupt,
1697 .suspend = brcm_fet_suspend,
1698 .resume = brcm_fet_config_init,
1699 .config_aneg = bcm5221_config_aneg,
1700 .read_status = bcm5221_read_status,
1701 }, {
1702 PHY_ID_MATCH_MODEL(PHY_ID_BCM5395),
1703 .name = "Broadcom BCM5395",
1704 .flags = PHY_IS_INTERNAL,
1705 /* PHY_GBIT_FEATURES */
1706 .get_sset_count = bcm_phy_get_sset_count,
1707 .get_strings = bcm_phy_get_strings,
1708 .get_stats = bcm54xx_get_stats,
1709 .probe = bcm54xx_phy_probe,
1710 .link_change_notify = bcm54xx_link_change_notify,
1711 .led_brightness_set = bcm_phy_led_brightness_set,
1712 }, {
1713 PHY_ID_MATCH_MODEL(PHY_ID_BCM53125),
1714 .name = "Broadcom BCM53125",
1715 .flags = PHY_IS_INTERNAL,
1716 /* PHY_GBIT_FEATURES */
1717 .get_sset_count = bcm_phy_get_sset_count,
1718 .get_strings = bcm_phy_get_strings,
1719 .get_stats = bcm54xx_get_stats,
1720 .probe = bcm54xx_phy_probe,
1721 .config_init = bcm54xx_config_init,
1722 .config_intr = bcm_phy_config_intr,
1723 .handle_interrupt = bcm_phy_handle_interrupt,
1724 .link_change_notify = bcm54xx_link_change_notify,
1725 .led_brightness_set = bcm_phy_led_brightness_set,
1726 }, {
1727 PHY_ID_MATCH_MODEL(PHY_ID_BCM53128),
1728 .name = "Broadcom BCM53128",
1729 .flags = PHY_IS_INTERNAL,
1730 /* PHY_GBIT_FEATURES */
1731 .get_sset_count = bcm_phy_get_sset_count,
1732 .get_strings = bcm_phy_get_strings,
1733 .get_stats = bcm54xx_get_stats,
1734 .probe = bcm54xx_phy_probe,
1735 .config_init = bcm54xx_config_init,
1736 .config_intr = bcm_phy_config_intr,
1737 .handle_interrupt = bcm_phy_handle_interrupt,
1738 .link_change_notify = bcm54xx_link_change_notify,
1739 .led_brightness_set = bcm_phy_led_brightness_set,
1740 }, {
1741 PHY_ID_MATCH_MODEL(PHY_ID_BCM89610),
1742 .name = "Broadcom BCM89610",
1743 /* PHY_GBIT_FEATURES */
1744 .get_sset_count = bcm_phy_get_sset_count,
1745 .get_strings = bcm_phy_get_strings,
1746 .get_stats = bcm54xx_get_stats,
1747 .probe = bcm54xx_phy_probe,
1748 .config_init = bcm54xx_config_init,
1749 .config_intr = bcm_phy_config_intr,
1750 .handle_interrupt = bcm_phy_handle_interrupt,
1751 .link_change_notify = bcm54xx_link_change_notify,
1752 } };
1753
1754 module_phy_driver(broadcom_drivers);
1755
1756 static const struct mdio_device_id __maybe_unused broadcom_tbl[] = {
1757 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5411) },
1758 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5421) },
1759 { PHY_ID_MATCH_MODEL(PHY_ID_BCM54210E) },
1760 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5461) },
1761 { PHY_ID_MATCH_MODEL(PHY_ID_BCM54612E) },
1762 { PHY_ID_MATCH_MODEL(PHY_ID_BCM54616S) },
1763 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5464) },
1764 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5481) },
1765 { PHY_ID_MATCH_MODEL(PHY_ID_BCM54810) },
1766 { PHY_ID_MATCH_MODEL(PHY_ID_BCM54811) },
1767 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5482) },
1768 { PHY_ID_MATCH_MODEL(PHY_ID_BCM50610) },
1769 { PHY_ID_MATCH_MODEL(PHY_ID_BCM50610M) },
1770 { PHY_ID_MATCH_MODEL(PHY_ID_BCM57780) },
1771 { PHY_ID_MATCH_MODEL(PHY_ID_BCMAC131) },
1772 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5221) },
1773 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5241) },
1774 { PHY_ID_MATCH_MODEL(PHY_ID_BCM5395) },
1775 { PHY_ID_MATCH_MODEL(PHY_ID_BCM53125) },
1776 { PHY_ID_MATCH_MODEL(PHY_ID_BCM53128) },
1777 { PHY_ID_MATCH_MODEL(PHY_ID_BCM89610) },
1778 { }
1779 };
1780
1781 MODULE_DEVICE_TABLE(mdio, broadcom_tbl);
1782