2 * Broadcom BCM7xxx internal transceivers support.
4 * Copyright (C) 2014-2017 Broadcom
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/module.h>
13 #include <linux/phy.h>
14 #include <linux/delay.h>
15 #include "bcm-phy-lib.h"
16 #include <linux/bitops.h>
17 #include <linux/brcmphy.h>
18 #include <linux/mdio.h>
20 /* Broadcom BCM7xxx internal PHY registers */
22 /* EPHY only register definitions */
23 #define MII_BCM7XXX_100TX_AUX_CTL 0x10
24 #define MII_BCM7XXX_100TX_FALSE_CAR 0x13
25 #define MII_BCM7XXX_100TX_DISC 0x14
26 #define MII_BCM7XXX_AUX_MODE 0x1d
27 #define MII_BCM7XXX_64CLK_MDIO BIT(12)
28 #define MII_BCM7XXX_TEST 0x1f
29 #define MII_BCM7XXX_SHD_MODE_2 BIT(2)
30 #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe
31 #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf
32 #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a
33 #define MII_BCM7XXX_SHD_3_PCS_CTRL 0x0
34 #define MII_BCM7XXX_SHD_3_PCS_STATUS 0x1
35 #define MII_BCM7XXX_SHD_3_EEE_CAP 0x2
36 #define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3
37 #define MII_BCM7XXX_SHD_3_EEE_LP 0x4
38 #define MII_BCM7XXX_SHD_3_EEE_WK_ERR 0x5
39 #define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6
40 #define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400
41 #define MII_BCM7XXX_SHD_3_AN_STAT 0xb
42 #define MII_BCM7XXX_AN_NULL_MSG_EN BIT(0)
43 #define MII_BCM7XXX_AN_EEE_EN BIT(1)
44 #define MII_BCM7XXX_SHD_3_EEE_THRESH 0xe
45 #define MII_BCM7XXX_EEE_THRESH_DEF 0x50
46 #define MII_BCM7XXX_SHD_3_TL4 0x23
47 #define MII_BCM7XXX_TL4_RST_MSK (BIT(2) | BIT(1))
49 /* 28nm only register definitions */
50 #define MISC_ADDR(base, channel) base, channel
52 #define DSP_TAP10 MISC_ADDR(0x0a, 0)
53 #define PLL_PLLCTRL_1 MISC_ADDR(0x32, 1)
54 #define PLL_PLLCTRL_2 MISC_ADDR(0x32, 2)
55 #define PLL_PLLCTRL_4 MISC_ADDR(0x33, 0)
57 #define AFE_RXCONFIG_0 MISC_ADDR(0x38, 0)
58 #define AFE_RXCONFIG_1 MISC_ADDR(0x38, 1)
59 #define AFE_RXCONFIG_2 MISC_ADDR(0x38, 2)
60 #define AFE_RX_LP_COUNTER MISC_ADDR(0x38, 3)
61 #define AFE_TX_CONFIG MISC_ADDR(0x39, 0)
62 #define AFE_VDCA_ICTRL_0 MISC_ADDR(0x39, 1)
63 #define AFE_VDAC_OTHERS_0 MISC_ADDR(0x39, 3)
64 #define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0)
66 struct bcm7xxx_phy_priv {
70 static void r_rc_cal_reset(struct phy_device *phydev)
72 /* Reset R_CAL/RC_CAL Engine */
73 bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010);
75 /* Disable Reset R_AL/RC_CAL Engine */
76 bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000);
79 static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
81 /* Increase VCO range to prevent unlocking problem of PLL at low
84 bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
86 /* Change Ki to 011 */
87 bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
89 /* Disable loading of TVCO buffer to bandgap, set bandgap trim
92 bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
94 /* Adjust bias current trim by -3 */
95 bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b);
97 /* Switch to CORE_BASE1E */
98 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd);
100 r_rc_cal_reset(phydev);
102 /* write AFE_RXCONFIG_0 */
103 bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
105 /* write AFE_RXCONFIG_1 */
106 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
108 /* write AFE_RX_LP_COUNTER */
109 bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
111 /* write AFE_HPF_TRIM_OTHERS */
112 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
114 /* write AFTE_TX_CONFIG */
115 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
120 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
123 bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
126 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
128 /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
129 bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
131 /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
132 bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
134 /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
135 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
137 /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
138 bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
140 /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
141 bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
143 /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
144 * offset for HT=0 code
146 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
148 /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
149 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
151 /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
152 bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
154 /* Reset R_CAL/RC_CAL engine */
155 r_rc_cal_reset(phydev);
160 static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
162 /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
163 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
165 /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
166 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
168 /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
169 bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
171 /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
172 * offset for HT=0 code
174 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
176 /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
177 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
179 /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
180 bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
182 /* Reset R_CAL/RC_CAL engine */
183 r_rc_cal_reset(phydev);
188 static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev)
190 /* +1 RC_CAL codes for RL centering for both LT and HT conditions */
191 bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
193 /* Cut master bias current by 2% to compensate for RC_CAL offset */
194 bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
196 /* Improve hybrid leakage */
197 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
199 /* Change rx_on_tune 8 to 0xf */
200 bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
202 /* Change 100Tx EEE bandwidth */
203 bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
205 /* Enable ffe zero detection for Vitesse interoperability */
206 bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015);
208 r_rc_cal_reset(phydev);
213 static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
215 u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
216 u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
220 /* Newer devices have moved the revision information back into a
221 * standard location in MII_PHYS_ID[23]
224 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
226 pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
227 phydev_name(phydev), phydev->drv->name, rev, patch);
229 /* Dummy read to a register to workaround an issue upon reset where the
230 * internal inverter may not allow the first MDIO transaction to pass
231 * the MDIO management controller and make us return 0xffff for such
234 phy_read(phydev, MII_BMSR);
239 ret = bcm7xxx_28nm_b0_afe_config_init(phydev);
242 ret = bcm7xxx_28nm_d0_afe_config_init(phydev);
246 /* Rev G0 introduces a roll over */
248 ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
251 ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
260 ret = bcm_phy_downshift_get(phydev, &count);
264 /* Only enable EEE if Wirespeed/downshift is disabled */
265 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
269 return bcm_phy_enable_apd(phydev, true);
272 static int bcm7xxx_28nm_resume(struct phy_device *phydev)
276 /* Re-apply workarounds coming out suspend/resume */
277 ret = bcm7xxx_28nm_config_init(phydev);
281 /* 28nm Gigabit PHYs come out of reset without any half-duplex
282 * or "hub" compliant advertised mode, fix that. This does not
283 * cause any problems with the PHY library since genphy_config_aneg()
284 * gracefully handles auto-negotiated and forced modes.
286 return genphy_config_aneg(phydev);
289 static int phy_set_clr_bits(struct phy_device *dev, int location,
290 int set_mask, int clr_mask)
294 v = phy_read(dev, location);
301 ret = phy_write(dev, location, v);
308 static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
312 /* set shadow mode 2 */
313 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
314 MII_BCM7XXX_SHD_MODE_2, 0);
318 /* Set current trim values INT_trim = -1, Ext_trim =0 */
319 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
321 goto reset_shadow_mode;
324 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
325 MII_BCM7XXX_SHD_3_TL4);
327 goto reset_shadow_mode;
328 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
329 MII_BCM7XXX_TL4_RST_MSK, 0);
331 goto reset_shadow_mode;
333 /* Cal reset disable */
334 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
335 MII_BCM7XXX_SHD_3_TL4);
337 goto reset_shadow_mode;
338 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
339 0, MII_BCM7XXX_TL4_RST_MSK);
341 goto reset_shadow_mode;
344 /* reset shadow mode 2 */
345 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
346 MII_BCM7XXX_SHD_MODE_2);
353 /* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */
354 static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
358 /* set shadow mode 1 */
359 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST,
360 MII_BRCM_FET_BT_SRE, 0);
364 /* Enable auto-power down */
365 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
366 MII_BRCM_FET_SHDW_AS2_APDE, 0);
370 /* reset shadow mode 1 */
371 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0,
372 MII_BRCM_FET_BT_SRE);
379 static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev)
383 /* set shadow mode 2 */
384 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
385 MII_BCM7XXX_SHD_MODE_2, 0);
389 /* Advertise supported modes */
390 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
391 MII_BCM7XXX_SHD_3_AN_EEE_ADV);
393 goto reset_shadow_mode;
394 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
397 goto reset_shadow_mode;
399 /* Restore Defaults */
400 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
401 MII_BCM7XXX_SHD_3_PCS_CTRL_2);
403 goto reset_shadow_mode;
404 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
405 MII_BCM7XXX_PCS_CTRL_2_DEF);
407 goto reset_shadow_mode;
409 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
410 MII_BCM7XXX_SHD_3_EEE_THRESH);
412 goto reset_shadow_mode;
413 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
414 MII_BCM7XXX_EEE_THRESH_DEF);
416 goto reset_shadow_mode;
418 /* Enable EEE autonegotiation */
419 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
420 MII_BCM7XXX_SHD_3_AN_STAT);
422 goto reset_shadow_mode;
423 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
424 (MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN));
426 goto reset_shadow_mode;
429 /* reset shadow mode 2 */
430 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
431 MII_BCM7XXX_SHD_MODE_2);
435 /* Restart autoneg */
436 phy_write(phydev, MII_BMCR,
437 (BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART));
442 static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
444 u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
447 pr_info_once("%s: %s PHY revision: 0x%02x\n",
448 phydev_name(phydev), phydev->drv->name, rev);
450 /* Dummy read to a register to workaround a possible issue upon reset
451 * where the internal inverter may not allow the first MDIO transaction
452 * to pass the MDIO management controller and make us return 0xffff for
455 phy_read(phydev, MII_BMSR);
457 /* Apply AFE software work-around if necessary */
459 ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev);
464 ret = bcm7xxx_28nm_ephy_eee_enable(phydev);
468 return bcm7xxx_28nm_ephy_apd_enable(phydev);
471 #define MII_BCM7XXX_REG_INVALID 0xff
473 static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
477 return MII_BCM7XXX_SHD_3_PCS_CTRL;
479 return MII_BCM7XXX_SHD_3_PCS_STATUS;
480 case MDIO_PCS_EEE_ABLE:
481 return MII_BCM7XXX_SHD_3_EEE_CAP;
482 case MDIO_AN_EEE_ADV:
483 return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
484 case MDIO_AN_EEE_LPABLE:
485 return MII_BCM7XXX_SHD_3_EEE_LP;
486 case MDIO_PCS_EEE_WK_ERR:
487 return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
489 return MII_BCM7XXX_REG_INVALID;
493 static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
495 return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
498 static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
499 int devnum, u16 regnum)
501 u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
504 if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
505 shd == MII_BCM7XXX_REG_INVALID)
508 /* set shadow mode 2 */
509 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
510 MII_BCM7XXX_SHD_MODE_2, 0);
514 /* Access the desired shadow register address */
515 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
517 goto reset_shadow_mode;
519 ret = phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
522 /* reset shadow mode 2 */
523 phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
524 MII_BCM7XXX_SHD_MODE_2);
528 static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
529 int devnum, u16 regnum, u16 val)
531 u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
534 if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
535 shd == MII_BCM7XXX_REG_INVALID)
538 /* set shadow mode 2 */
539 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
540 MII_BCM7XXX_SHD_MODE_2, 0);
544 /* Access the desired shadow register address */
545 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
547 goto reset_shadow_mode;
549 /* Write the desired value in the shadow register */
550 phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
553 /* reset shadow mode 2 */
554 return phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
555 MII_BCM7XXX_SHD_MODE_2);
558 static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
562 /* Re-apply workarounds coming out suspend/resume */
563 ret = bcm7xxx_28nm_ephy_config_init(phydev);
567 return genphy_config_aneg(phydev);
570 static int bcm7xxx_config_init(struct phy_device *phydev)
574 /* Enable 64 clock MDIO */
575 phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO);
576 phy_read(phydev, MII_BCM7XXX_AUX_MODE);
578 /* set shadow mode 2 */
579 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
580 MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
584 /* set iddq_clkbias */
585 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
588 /* reset iddq_clkbias */
589 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
591 phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
593 /* reset shadow mode 2 */
594 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2);
601 /* Workaround for putting the PHY in IDDQ mode, required
602 * for all BCM7XXX 40nm and 65nm PHYs
604 static int bcm7xxx_suspend(struct phy_device *phydev)
607 static const struct bcm7xxx_regs {
610 } bcm7xxx_suspend_cfg[] = {
611 { MII_BCM7XXX_TEST, 0x008b },
612 { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 },
613 { MII_BCM7XXX_100TX_DISC, 0x7000 },
614 { MII_BCM7XXX_TEST, 0x000f },
615 { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 },
616 { MII_BCM7XXX_TEST, 0x000b },
620 for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) {
621 ret = phy_write(phydev,
622 bcm7xxx_suspend_cfg[i].reg,
623 bcm7xxx_suspend_cfg[i].value);
631 static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev,
632 struct ethtool_tunable *tuna,
636 case ETHTOOL_PHY_DOWNSHIFT:
637 return bcm_phy_downshift_get(phydev, (u8 *)data);
643 static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev,
644 struct ethtool_tunable *tuna,
647 u8 count = *(u8 *)data;
651 case ETHTOOL_PHY_DOWNSHIFT:
652 ret = bcm_phy_downshift_set(phydev, count);
661 /* Disable EEE advertisement since this prevents the PHY
662 * from successfully linking up, trigger auto-negotiation restart
663 * to let the MAC decide what to do.
665 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
669 return genphy_restart_aneg(phydev);
672 static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
673 struct ethtool_stats *stats, u64 *data)
675 struct bcm7xxx_phy_priv *priv = phydev->priv;
677 bcm_phy_get_stats(phydev, priv->stats, stats, data);
680 static int bcm7xxx_28nm_probe(struct phy_device *phydev)
682 struct bcm7xxx_phy_priv *priv;
684 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
690 priv->stats = devm_kcalloc(&phydev->mdio.dev,
691 bcm_phy_get_sset_count(phydev), sizeof(u64),
699 #define BCM7XXX_28NM_GPHY(_oui, _name) \
702 .phy_id_mask = 0xfffffff0, \
704 .features = PHY_GBIT_FEATURES, \
705 .flags = PHY_IS_INTERNAL, \
706 .config_init = bcm7xxx_28nm_config_init, \
707 .resume = bcm7xxx_28nm_resume, \
708 .get_tunable = bcm7xxx_28nm_get_tunable, \
709 .set_tunable = bcm7xxx_28nm_set_tunable, \
710 .get_sset_count = bcm_phy_get_sset_count, \
711 .get_strings = bcm_phy_get_strings, \
712 .get_stats = bcm7xxx_28nm_get_phy_stats, \
713 .probe = bcm7xxx_28nm_probe, \
716 #define BCM7XXX_28NM_EPHY(_oui, _name) \
719 .phy_id_mask = 0xfffffff0, \
721 .features = PHY_BASIC_FEATURES, \
722 .flags = PHY_IS_INTERNAL, \
723 .config_init = bcm7xxx_28nm_ephy_config_init, \
724 .resume = bcm7xxx_28nm_ephy_resume, \
725 .get_sset_count = bcm_phy_get_sset_count, \
726 .get_strings = bcm_phy_get_strings, \
727 .get_stats = bcm7xxx_28nm_get_phy_stats, \
728 .probe = bcm7xxx_28nm_probe, \
729 .read_mmd = bcm7xxx_28nm_ephy_read_mmd, \
730 .write_mmd = bcm7xxx_28nm_ephy_write_mmd, \
733 #define BCM7XXX_40NM_EPHY(_oui, _name) \
736 .phy_id_mask = 0xfffffff0, \
738 .features = PHY_BASIC_FEATURES, \
739 .flags = PHY_IS_INTERNAL, \
740 .soft_reset = genphy_soft_reset, \
741 .config_init = bcm7xxx_config_init, \
742 .suspend = bcm7xxx_suspend, \
743 .resume = bcm7xxx_config_init, \
746 static struct phy_driver bcm7xxx_driver[] = {
747 BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
748 BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"),
749 BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"),
750 BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"),
751 BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
752 BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
753 BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
754 BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"),
755 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
756 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"),
757 BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"),
758 BCM7XXX_28NM_GPHY(PHY_ID_BCM_OMEGA, "Broadcom Omega Combo GPHY"),
759 BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"),
760 BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"),
761 BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"),
762 BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"),
763 BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"),
766 static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
767 { PHY_ID_BCM7250, 0xfffffff0, },
768 { PHY_ID_BCM7260, 0xfffffff0, },
769 { PHY_ID_BCM7268, 0xfffffff0, },
770 { PHY_ID_BCM7271, 0xfffffff0, },
771 { PHY_ID_BCM7278, 0xfffffff0, },
772 { PHY_ID_BCM7364, 0xfffffff0, },
773 { PHY_ID_BCM7366, 0xfffffff0, },
774 { PHY_ID_BCM7346, 0xfffffff0, },
775 { PHY_ID_BCM7362, 0xfffffff0, },
776 { PHY_ID_BCM7425, 0xfffffff0, },
777 { PHY_ID_BCM7429, 0xfffffff0, },
778 { PHY_ID_BCM74371, 0xfffffff0, },
779 { PHY_ID_BCM7439, 0xfffffff0, },
780 { PHY_ID_BCM7435, 0xfffffff0, },
781 { PHY_ID_BCM7445, 0xfffffff0, },
785 module_phy_driver(bcm7xxx_driver);
787 MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl);
789 MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver");
790 MODULE_LICENSE("GPL");
791 MODULE_AUTHOR("Broadcom Corporation");