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);
238 ret = bcm7xxx_28nm_b0_afe_config_init(phydev);
241 ret = bcm7xxx_28nm_d0_afe_config_init(phydev);
245 /* Rev G0 introduces a roll over */
247 ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
250 ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
259 ret = bcm_phy_downshift_get(phydev, &count);
263 /* Only enable EEE if Wirespeed/downshift is disabled */
264 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
268 return bcm_phy_enable_apd(phydev, true);
271 static int bcm7xxx_28nm_resume(struct phy_device *phydev)
275 /* Re-apply workarounds coming out suspend/resume */
276 ret = bcm7xxx_28nm_config_init(phydev);
280 /* 28nm Gigabit PHYs come out of reset without any half-duplex
281 * or "hub" compliant advertised mode, fix that. This does not
282 * cause any problems with the PHY library since genphy_config_aneg()
283 * gracefully handles auto-negotiated and forced modes.
285 return genphy_config_aneg(phydev);
288 static int phy_set_clr_bits(struct phy_device *dev, int location,
289 int set_mask, int clr_mask)
293 v = phy_read(dev, location);
300 ret = phy_write(dev, location, v);
307 static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
311 /* set shadow mode 2 */
312 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
313 MII_BCM7XXX_SHD_MODE_2, 0);
317 /* Set current trim values INT_trim = -1, Ext_trim =0 */
318 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
320 goto reset_shadow_mode;
323 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
324 MII_BCM7XXX_SHD_3_TL4);
326 goto reset_shadow_mode;
327 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
328 MII_BCM7XXX_TL4_RST_MSK, 0);
330 goto reset_shadow_mode;
332 /* Cal reset disable */
333 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
334 MII_BCM7XXX_SHD_3_TL4);
336 goto reset_shadow_mode;
337 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
338 0, MII_BCM7XXX_TL4_RST_MSK);
340 goto reset_shadow_mode;
343 /* reset shadow mode 2 */
344 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
345 MII_BCM7XXX_SHD_MODE_2);
352 /* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */
353 static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
357 /* set shadow mode 1 */
358 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST,
359 MII_BRCM_FET_BT_SRE, 0);
363 /* Enable auto-power down */
364 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
365 MII_BRCM_FET_SHDW_AS2_APDE, 0);
369 /* reset shadow mode 1 */
370 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0,
371 MII_BRCM_FET_BT_SRE);
378 static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev)
382 /* set shadow mode 2 */
383 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
384 MII_BCM7XXX_SHD_MODE_2, 0);
388 /* Advertise supported modes */
389 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
390 MII_BCM7XXX_SHD_3_AN_EEE_ADV);
392 goto reset_shadow_mode;
393 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
396 goto reset_shadow_mode;
398 /* Restore Defaults */
399 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
400 MII_BCM7XXX_SHD_3_PCS_CTRL_2);
402 goto reset_shadow_mode;
403 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
404 MII_BCM7XXX_PCS_CTRL_2_DEF);
406 goto reset_shadow_mode;
408 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
409 MII_BCM7XXX_SHD_3_EEE_THRESH);
411 goto reset_shadow_mode;
412 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
413 MII_BCM7XXX_EEE_THRESH_DEF);
415 goto reset_shadow_mode;
417 /* Enable EEE autonegotiation */
418 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
419 MII_BCM7XXX_SHD_3_AN_STAT);
421 goto reset_shadow_mode;
422 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
423 (MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN));
425 goto reset_shadow_mode;
428 /* reset shadow mode 2 */
429 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
430 MII_BCM7XXX_SHD_MODE_2);
434 /* Restart autoneg */
435 phy_write(phydev, MII_BMCR,
436 (BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART));
441 static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
443 u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
446 pr_info_once("%s: %s PHY revision: 0x%02x\n",
447 phydev_name(phydev), phydev->drv->name, rev);
449 /* Dummy read to a register to workaround a possible issue upon reset
450 * where the internal inverter may not allow the first MDIO transaction
451 * to pass the MDIO management controller and make us return 0xffff for
454 phy_read(phydev, MII_BMSR);
456 /* Apply AFE software work-around if necessary */
458 ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev);
463 ret = bcm7xxx_28nm_ephy_eee_enable(phydev);
467 return bcm7xxx_28nm_ephy_apd_enable(phydev);
470 #define MII_BCM7XXX_REG_INVALID 0xff
472 static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
476 return MII_BCM7XXX_SHD_3_PCS_CTRL;
478 return MII_BCM7XXX_SHD_3_PCS_STATUS;
479 case MDIO_PCS_EEE_ABLE:
480 return MII_BCM7XXX_SHD_3_EEE_CAP;
481 case MDIO_AN_EEE_ADV:
482 return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
483 case MDIO_AN_EEE_LPABLE:
484 return MII_BCM7XXX_SHD_3_EEE_LP;
485 case MDIO_PCS_EEE_WK_ERR:
486 return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
488 return MII_BCM7XXX_REG_INVALID;
492 static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
494 return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
497 static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
498 int devnum, u16 regnum)
500 u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
503 if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
504 shd == MII_BCM7XXX_REG_INVALID)
507 /* set shadow mode 2 */
508 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
509 MII_BCM7XXX_SHD_MODE_2, 0);
513 /* Access the desired shadow register address */
514 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
516 goto reset_shadow_mode;
518 ret = phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
521 /* reset shadow mode 2 */
522 phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
523 MII_BCM7XXX_SHD_MODE_2);
527 static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
528 int devnum, u16 regnum, u16 val)
530 u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
533 if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
534 shd == MII_BCM7XXX_REG_INVALID)
537 /* set shadow mode 2 */
538 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
539 MII_BCM7XXX_SHD_MODE_2, 0);
543 /* Access the desired shadow register address */
544 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
546 goto reset_shadow_mode;
548 /* Write the desired value in the shadow register */
549 phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
552 /* reset shadow mode 2 */
553 return phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
554 MII_BCM7XXX_SHD_MODE_2);
557 static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
561 /* Re-apply workarounds coming out suspend/resume */
562 ret = bcm7xxx_28nm_ephy_config_init(phydev);
566 return genphy_config_aneg(phydev);
569 static int bcm7xxx_config_init(struct phy_device *phydev)
573 /* Enable 64 clock MDIO */
574 phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO);
575 phy_read(phydev, MII_BCM7XXX_AUX_MODE);
577 /* set shadow mode 2 */
578 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
579 MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
583 /* set iddq_clkbias */
584 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
587 /* reset iddq_clkbias */
588 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
590 phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
592 /* reset shadow mode 2 */
593 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2);
600 /* Workaround for putting the PHY in IDDQ mode, required
601 * for all BCM7XXX 40nm and 65nm PHYs
603 static int bcm7xxx_suspend(struct phy_device *phydev)
606 static const struct bcm7xxx_regs {
609 } bcm7xxx_suspend_cfg[] = {
610 { MII_BCM7XXX_TEST, 0x008b },
611 { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 },
612 { MII_BCM7XXX_100TX_DISC, 0x7000 },
613 { MII_BCM7XXX_TEST, 0x000f },
614 { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 },
615 { MII_BCM7XXX_TEST, 0x000b },
619 for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) {
620 ret = phy_write(phydev,
621 bcm7xxx_suspend_cfg[i].reg,
622 bcm7xxx_suspend_cfg[i].value);
630 static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev,
631 struct ethtool_tunable *tuna,
635 case ETHTOOL_PHY_DOWNSHIFT:
636 return bcm_phy_downshift_get(phydev, (u8 *)data);
642 static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev,
643 struct ethtool_tunable *tuna,
646 u8 count = *(u8 *)data;
650 case ETHTOOL_PHY_DOWNSHIFT:
651 ret = bcm_phy_downshift_set(phydev, count);
660 /* Disable EEE advertisment since this prevents the PHY
661 * from successfully linking up, trigger auto-negotiation restart
662 * to let the MAC decide what to do.
664 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
668 return genphy_restart_aneg(phydev);
671 static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
672 struct ethtool_stats *stats, u64 *data)
674 struct bcm7xxx_phy_priv *priv = phydev->priv;
676 bcm_phy_get_stats(phydev, priv->stats, stats, data);
679 static int bcm7xxx_28nm_probe(struct phy_device *phydev)
681 struct bcm7xxx_phy_priv *priv;
683 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
689 priv->stats = devm_kcalloc(&phydev->mdio.dev,
690 bcm_phy_get_sset_count(phydev), sizeof(u64),
698 #define BCM7XXX_28NM_GPHY(_oui, _name) \
701 .phy_id_mask = 0xfffffff0, \
703 .features = PHY_GBIT_FEATURES, \
704 .flags = PHY_IS_INTERNAL, \
705 .config_init = bcm7xxx_28nm_config_init, \
706 .config_aneg = genphy_config_aneg, \
707 .read_status = genphy_read_status, \
708 .resume = bcm7xxx_28nm_resume, \
709 .get_tunable = bcm7xxx_28nm_get_tunable, \
710 .set_tunable = bcm7xxx_28nm_set_tunable, \
711 .get_sset_count = bcm_phy_get_sset_count, \
712 .get_strings = bcm_phy_get_strings, \
713 .get_stats = bcm7xxx_28nm_get_phy_stats, \
714 .probe = bcm7xxx_28nm_probe, \
717 #define BCM7XXX_28NM_EPHY(_oui, _name) \
720 .phy_id_mask = 0xfffffff0, \
722 .features = PHY_BASIC_FEATURES, \
723 .flags = PHY_IS_INTERNAL, \
724 .config_init = bcm7xxx_28nm_ephy_config_init, \
725 .config_aneg = genphy_config_aneg, \
726 .read_status = genphy_read_status, \
727 .resume = bcm7xxx_28nm_ephy_resume, \
728 .get_sset_count = bcm_phy_get_sset_count, \
729 .get_strings = bcm_phy_get_strings, \
730 .get_stats = bcm7xxx_28nm_get_phy_stats, \
731 .probe = bcm7xxx_28nm_probe, \
732 .read_mmd = bcm7xxx_28nm_ephy_read_mmd, \
733 .write_mmd = bcm7xxx_28nm_ephy_write_mmd, \
736 #define BCM7XXX_40NM_EPHY(_oui, _name) \
739 .phy_id_mask = 0xfffffff0, \
741 .features = PHY_BASIC_FEATURES, \
742 .flags = PHY_IS_INTERNAL, \
743 .config_init = bcm7xxx_config_init, \
744 .config_aneg = genphy_config_aneg, \
745 .read_status = genphy_read_status, \
746 .suspend = bcm7xxx_suspend, \
747 .resume = bcm7xxx_config_init, \
750 static struct phy_driver bcm7xxx_driver[] = {
751 BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
752 BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"),
753 BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"),
754 BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"),
755 BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
756 BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
757 BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
758 BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"),
759 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
760 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"),
761 BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"),
762 BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"),
763 BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"),
764 BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"),
765 BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"),
766 BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"),
769 static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
770 { PHY_ID_BCM7250, 0xfffffff0, },
771 { PHY_ID_BCM7260, 0xfffffff0, },
772 { PHY_ID_BCM7268, 0xfffffff0, },
773 { PHY_ID_BCM7271, 0xfffffff0, },
774 { PHY_ID_BCM7278, 0xfffffff0, },
775 { PHY_ID_BCM7364, 0xfffffff0, },
776 { PHY_ID_BCM7366, 0xfffffff0, },
777 { PHY_ID_BCM7346, 0xfffffff0, },
778 { PHY_ID_BCM7362, 0xfffffff0, },
779 { PHY_ID_BCM7425, 0xfffffff0, },
780 { PHY_ID_BCM7429, 0xfffffff0, },
781 { PHY_ID_BCM74371, 0xfffffff0, },
782 { PHY_ID_BCM7439, 0xfffffff0, },
783 { PHY_ID_BCM7435, 0xfffffff0, },
784 { PHY_ID_BCM7445, 0xfffffff0, },
788 module_phy_driver(bcm7xxx_driver);
790 MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl);
792 MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver");
793 MODULE_LICENSE("GPL");
794 MODULE_AUTHOR("Broadcom Corporation");