Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Broadcom BCM7xxx internal transceivers support.
0004  *
0005  * Copyright (C) 2014-2017 Broadcom
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/phy.h>
0010 #include <linux/delay.h>
0011 #include "bcm-phy-lib.h"
0012 #include <linux/bitops.h>
0013 #include <linux/brcmphy.h>
0014 #include <linux/clk.h>
0015 #include <linux/mdio.h>
0016 
0017 /* Broadcom BCM7xxx internal PHY registers */
0018 
0019 /* EPHY only register definitions */
0020 #define MII_BCM7XXX_100TX_AUX_CTL   0x10
0021 #define MII_BCM7XXX_100TX_FALSE_CAR 0x13
0022 #define MII_BCM7XXX_100TX_DISC      0x14
0023 #define MII_BCM7XXX_AUX_MODE        0x1d
0024 #define  MII_BCM7XXX_64CLK_MDIO     BIT(12)
0025 #define MII_BCM7XXX_TEST        0x1f
0026 #define  MII_BCM7XXX_SHD_MODE_2     BIT(2)
0027 #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe
0028 #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf
0029 #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a
0030 #define MII_BCM7XXX_SHD_3_PCS_CTRL  0x0
0031 #define MII_BCM7XXX_SHD_3_PCS_STATUS    0x1
0032 #define MII_BCM7XXX_SHD_3_EEE_CAP   0x2
0033 #define MII_BCM7XXX_SHD_3_AN_EEE_ADV    0x3
0034 #define MII_BCM7XXX_SHD_3_EEE_LP    0x4
0035 #define MII_BCM7XXX_SHD_3_EEE_WK_ERR    0x5
0036 #define MII_BCM7XXX_SHD_3_PCS_CTRL_2    0x6
0037 #define  MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400
0038 #define MII_BCM7XXX_SHD_3_AN_STAT   0xb
0039 #define  MII_BCM7XXX_AN_NULL_MSG_EN BIT(0)
0040 #define  MII_BCM7XXX_AN_EEE_EN      BIT(1)
0041 #define MII_BCM7XXX_SHD_3_EEE_THRESH    0xe
0042 #define  MII_BCM7XXX_EEE_THRESH_DEF 0x50
0043 #define MII_BCM7XXX_SHD_3_TL4       0x23
0044 #define  MII_BCM7XXX_TL4_RST_MSK    (BIT(2) | BIT(1))
0045 
0046 struct bcm7xxx_phy_priv {
0047     u64 *stats;
0048     struct clk *clk;
0049 };
0050 
0051 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
0052 {
0053     /* AFE_RXCONFIG_0 */
0054     bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
0055 
0056     /* AFE_RXCONFIG_1 */
0057     bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
0058 
0059     /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
0060     bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
0061 
0062     /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
0063     bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
0064 
0065     /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
0066     bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
0067 
0068     /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
0069     bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
0070 
0071     /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
0072     bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
0073 
0074     /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
0075      * offset for HT=0 code
0076      */
0077     bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
0078 
0079     /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
0080     phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
0081 
0082     /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
0083     bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
0084 
0085     /* Reset R_CAL/RC_CAL engine */
0086     bcm_phy_r_rc_cal_reset(phydev);
0087 
0088     return 0;
0089 }
0090 
0091 static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
0092 {
0093     /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
0094     bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
0095 
0096     /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
0097     bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
0098 
0099     /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
0100     bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
0101 
0102     /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
0103      * offset for HT=0 code
0104      */
0105     bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
0106 
0107     /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
0108     phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
0109 
0110     /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
0111     bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
0112 
0113     /* Reset R_CAL/RC_CAL engine */
0114     bcm_phy_r_rc_cal_reset(phydev);
0115 
0116     return 0;
0117 }
0118 
0119 static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev)
0120 {
0121     /* +1 RC_CAL codes for RL centering for both LT and HT conditions */
0122     bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
0123 
0124     /* Cut master bias current by 2% to compensate for RC_CAL offset */
0125     bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
0126 
0127     /* Improve hybrid leakage */
0128     bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
0129 
0130     /* Change rx_on_tune 8 to 0xf */
0131     bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
0132 
0133     /* Change 100Tx EEE bandwidth */
0134     bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
0135 
0136     /* Enable ffe zero detection for Vitesse interoperability */
0137     bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015);
0138 
0139     bcm_phy_r_rc_cal_reset(phydev);
0140 
0141     return 0;
0142 }
0143 
0144 static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
0145 {
0146     u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
0147     u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
0148     u8 count;
0149     int ret = 0;
0150 
0151     /* Newer devices have moved the revision information back into a
0152      * standard location in MII_PHYS_ID[23]
0153      */
0154     if (rev == 0)
0155         rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
0156 
0157     pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
0158              phydev_name(phydev), phydev->drv->name, rev, patch);
0159 
0160     /* Dummy read to a register to workaround an issue upon reset where the
0161      * internal inverter may not allow the first MDIO transaction to pass
0162      * the MDIO management controller and make us return 0xffff for such
0163      * reads.
0164      */
0165     phy_read(phydev, MII_BMSR);
0166 
0167     switch (rev) {
0168     case 0xa0:
0169     case 0xb0:
0170         ret = bcm_phy_28nm_a0b0_afe_config_init(phydev);
0171         break;
0172     case 0xd0:
0173         ret = bcm7xxx_28nm_d0_afe_config_init(phydev);
0174         break;
0175     case 0xe0:
0176     case 0xf0:
0177     /* Rev G0 introduces a roll over */
0178     case 0x10:
0179         ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
0180         break;
0181     case 0x01:
0182         ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
0183         break;
0184     default:
0185         break;
0186     }
0187 
0188     if (ret)
0189         return ret;
0190 
0191     ret =  bcm_phy_enable_jumbo(phydev);
0192     if (ret)
0193         return ret;
0194 
0195     ret = bcm_phy_downshift_get(phydev, &count);
0196     if (ret)
0197         return ret;
0198 
0199     /* Only enable EEE if Wirespeed/downshift is disabled */
0200     ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
0201     if (ret)
0202         return ret;
0203 
0204     return bcm_phy_enable_apd(phydev, true);
0205 }
0206 
0207 static int bcm7xxx_28nm_resume(struct phy_device *phydev)
0208 {
0209     int ret;
0210 
0211     /* Re-apply workarounds coming out suspend/resume */
0212     ret = bcm7xxx_28nm_config_init(phydev);
0213     if (ret)
0214         return ret;
0215 
0216     /* 28nm Gigabit PHYs come out of reset without any half-duplex
0217      * or "hub" compliant advertised mode, fix that. This does not
0218      * cause any problems with the PHY library since genphy_config_aneg()
0219      * gracefully handles auto-negotiated and forced modes.
0220      */
0221     return genphy_config_aneg(phydev);
0222 }
0223 
0224 static int __phy_set_clr_bits(struct phy_device *dev, int location,
0225                   int set_mask, int clr_mask)
0226 {
0227     int v, ret;
0228 
0229     v = __phy_read(dev, location);
0230     if (v < 0)
0231         return v;
0232 
0233     v &= ~clr_mask;
0234     v |= set_mask;
0235 
0236     ret = __phy_write(dev, location, v);
0237     if (ret < 0)
0238         return ret;
0239 
0240     return v;
0241 }
0242 
0243 static int phy_set_clr_bits(struct phy_device *dev, int location,
0244                 int set_mask, int clr_mask)
0245 {
0246     int ret;
0247 
0248     mutex_lock(&dev->mdio.bus->mdio_lock);
0249     ret = __phy_set_clr_bits(dev, location, set_mask, clr_mask);
0250     mutex_unlock(&dev->mdio.bus->mdio_lock);
0251 
0252     return ret;
0253 }
0254 
0255 static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
0256 {
0257     int ret;
0258 
0259     /* set shadow mode 2 */
0260     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
0261                    MII_BCM7XXX_SHD_MODE_2, 0);
0262     if (ret < 0)
0263         return ret;
0264 
0265     /* Set current trim values INT_trim = -1, Ext_trim =0 */
0266     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
0267     if (ret < 0)
0268         goto reset_shadow_mode;
0269 
0270     /* Cal reset */
0271     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
0272             MII_BCM7XXX_SHD_3_TL4);
0273     if (ret < 0)
0274         goto reset_shadow_mode;
0275     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0276                    MII_BCM7XXX_TL4_RST_MSK, 0);
0277     if (ret < 0)
0278         goto reset_shadow_mode;
0279 
0280     /* Cal reset disable */
0281     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
0282             MII_BCM7XXX_SHD_3_TL4);
0283     if (ret < 0)
0284         goto reset_shadow_mode;
0285     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0286                    0, MII_BCM7XXX_TL4_RST_MSK);
0287     if (ret < 0)
0288         goto reset_shadow_mode;
0289 
0290 reset_shadow_mode:
0291     /* reset shadow mode 2 */
0292     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
0293                    MII_BCM7XXX_SHD_MODE_2);
0294     if (ret < 0)
0295         return ret;
0296 
0297     return 0;
0298 }
0299 
0300 /* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */
0301 static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
0302 {
0303     int ret;
0304 
0305     /* set shadow mode 1 */
0306     ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST,
0307                    MII_BRCM_FET_BT_SRE, 0);
0308     if (ret < 0)
0309         return ret;
0310 
0311     /* Enable auto-power down */
0312     ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
0313                    MII_BRCM_FET_SHDW_AS2_APDE, 0);
0314     if (ret < 0)
0315         return ret;
0316 
0317     /* reset shadow mode 1 */
0318     ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0,
0319                    MII_BRCM_FET_BT_SRE);
0320     if (ret < 0)
0321         return ret;
0322 
0323     return 0;
0324 }
0325 
0326 static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev)
0327 {
0328     int ret;
0329 
0330     /* set shadow mode 2 */
0331     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
0332                    MII_BCM7XXX_SHD_MODE_2, 0);
0333     if (ret < 0)
0334         return ret;
0335 
0336     /* Advertise supported modes */
0337     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
0338             MII_BCM7XXX_SHD_3_AN_EEE_ADV);
0339     if (ret < 0)
0340         goto reset_shadow_mode;
0341     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0342             MDIO_EEE_100TX);
0343     if (ret < 0)
0344         goto reset_shadow_mode;
0345 
0346     /* Restore Defaults */
0347     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
0348             MII_BCM7XXX_SHD_3_PCS_CTRL_2);
0349     if (ret < 0)
0350         goto reset_shadow_mode;
0351     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0352             MII_BCM7XXX_PCS_CTRL_2_DEF);
0353     if (ret < 0)
0354         goto reset_shadow_mode;
0355 
0356     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
0357             MII_BCM7XXX_SHD_3_EEE_THRESH);
0358     if (ret < 0)
0359         goto reset_shadow_mode;
0360     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0361             MII_BCM7XXX_EEE_THRESH_DEF);
0362     if (ret < 0)
0363         goto reset_shadow_mode;
0364 
0365     /* Enable EEE autonegotiation */
0366     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
0367             MII_BCM7XXX_SHD_3_AN_STAT);
0368     if (ret < 0)
0369         goto reset_shadow_mode;
0370     ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
0371             (MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN));
0372     if (ret < 0)
0373         goto reset_shadow_mode;
0374 
0375 reset_shadow_mode:
0376     /* reset shadow mode 2 */
0377     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
0378                    MII_BCM7XXX_SHD_MODE_2);
0379     if (ret < 0)
0380         return ret;
0381 
0382     /* Restart autoneg */
0383     phy_write(phydev, MII_BMCR,
0384           (BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART));
0385 
0386     return 0;
0387 }
0388 
0389 static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
0390 {
0391     u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
0392     int ret = 0;
0393 
0394     pr_info_once("%s: %s PHY revision: 0x%02x\n",
0395              phydev_name(phydev), phydev->drv->name, rev);
0396 
0397     /* Dummy read to a register to workaround a possible issue upon reset
0398      * where the internal inverter may not allow the first MDIO transaction
0399      * to pass the MDIO management controller and make us return 0xffff for
0400      * such reads.
0401      */
0402     phy_read(phydev, MII_BMSR);
0403 
0404     /* Apply AFE software work-around if necessary */
0405     if (rev == 0x01) {
0406         ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev);
0407         if (ret)
0408             return ret;
0409     }
0410 
0411     ret = bcm7xxx_28nm_ephy_eee_enable(phydev);
0412     if (ret)
0413         return ret;
0414 
0415     return bcm7xxx_28nm_ephy_apd_enable(phydev);
0416 }
0417 
0418 static int bcm7xxx_16nm_ephy_afe_config(struct phy_device *phydev)
0419 {
0420     int tmp, rcalcode, rcalnewcodelp, rcalnewcode11, rcalnewcode11d2;
0421 
0422     /* Reset PHY */
0423     tmp = genphy_soft_reset(phydev);
0424     if (tmp)
0425         return tmp;
0426 
0427     /* Reset AFE and PLL */
0428     bcm_phy_write_exp_sel(phydev, 0x0003, 0x0006);
0429     /* Clear reset */
0430     bcm_phy_write_exp_sel(phydev, 0x0003, 0x0000);
0431 
0432     /* Write PLL/AFE control register to select 54MHz crystal */
0433     bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0000);
0434     bcm_phy_write_misc(phydev, 0x0031, 0x0000, 0x044a);
0435 
0436     /* Change Ka,Kp,Ki to pdiv=1 */
0437     bcm_phy_write_misc(phydev, 0x0033, 0x0002, 0x71a1);
0438     /* Configuration override */
0439     bcm_phy_write_misc(phydev, 0x0033, 0x0001, 0x8000);
0440 
0441     /* Change PLL_NDIV and PLL_NUDGE */
0442     bcm_phy_write_misc(phydev, 0x0031, 0x0001, 0x2f68);
0443     bcm_phy_write_misc(phydev, 0x0031, 0x0002, 0x0000);
0444 
0445     /* Reference frequency is 54Mhz, config_mode[15:14] = 3 (low
0446      * phase)
0447      */
0448     bcm_phy_write_misc(phydev, 0x0030, 0x0003, 0xc036);
0449 
0450     /* Initialize bypass mode */
0451     bcm_phy_write_misc(phydev, 0x0032, 0x0003, 0x0000);
0452     /* Bypass code, default: VCOCLK enabled */
0453     bcm_phy_write_misc(phydev, 0x0033, 0x0000, 0x0002);
0454     /* LDOs at default setting */
0455     bcm_phy_write_misc(phydev, 0x0030, 0x0002, 0x01c0);
0456     /* Release PLL reset */
0457     bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0001);
0458 
0459     /* Bandgap curvature correction to correct default */
0460     bcm_phy_write_misc(phydev, 0x0038, 0x0000, 0x0010);
0461 
0462     /* Run RCAL */
0463     bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x0038);
0464     bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x003b);
0465     udelay(2);
0466     bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x003f);
0467     mdelay(5);
0468 
0469     /* AFE_CAL_CONFIG_0, Vref=1000, Target=10, averaging enabled */
0470     bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x1c82);
0471     /* AFE_CAL_CONFIG_0, no reset and analog powerup */
0472     bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e82);
0473     udelay(2);
0474     /* AFE_CAL_CONFIG_0, start calibration */
0475     bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f82);
0476     udelay(100);
0477     /* AFE_CAL_CONFIG_0, clear start calibration, set HiBW */
0478     bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e86);
0479     udelay(2);
0480     /* AFE_CAL_CONFIG_0, start calibration with hi BW mode set */
0481     bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f86);
0482     udelay(100);
0483 
0484     /* Adjust 10BT amplitude additional +7% and 100BT +2% */
0485     bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7ea);
0486     /* Adjust 1G mode amplitude and 1G testmode1 */
0487     bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0);
0488 
0489     /* Read CORE_EXPA9 */
0490     tmp = bcm_phy_read_exp(phydev, 0x00a9);
0491     /* CORE_EXPA9[6:1] is rcalcode[5:0] */
0492     rcalcode = (tmp & 0x7e) / 2;
0493     /* Correct RCAL code + 1 is -1% rprogr, LP: +16 */
0494     rcalnewcodelp = rcalcode + 16;
0495     /* Correct RCAL code + 1 is -15 rprogr, 11: +10 */
0496     rcalnewcode11 = rcalcode + 10;
0497     /* Saturate if necessary */
0498     if (rcalnewcodelp > 0x3f)
0499         rcalnewcodelp = 0x3f;
0500     if (rcalnewcode11 > 0x3f)
0501         rcalnewcode11 = 0x3f;
0502     /* REXT=1 BYP=1 RCAL_st1<5:0>=new rcal code */
0503     tmp = 0x00f8 + rcalnewcodelp * 256;
0504     /* Program into AFE_CAL_CONFIG_2 */
0505     bcm_phy_write_misc(phydev, 0x0039, 0x0003, tmp);
0506     /* AFE_BIAS_CONFIG_0 10BT bias code (Bias: E4) */
0507     bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7e4);
0508     /* invert adc clock output and 'adc refp ldo current To correct
0509      * default
0510      */
0511     bcm_phy_write_misc(phydev, 0x003b, 0x0000, 0x8002);
0512     /* 100BT stair case, high BW, 1G stair case, alternate encode */
0513     bcm_phy_write_misc(phydev, 0x003c, 0x0003, 0xf882);
0514     /* 1000BT DAC transition method per Erol, bits[32], DAC Shuffle
0515      * sequence 1 + 10BT imp adjust bits
0516      */
0517     bcm_phy_write_misc(phydev, 0x003d, 0x0000, 0x3201);
0518     /* Non-overlap fix */
0519     bcm_phy_write_misc(phydev, 0x003a, 0x0002, 0x0c00);
0520 
0521     /* pwdb override (rxconfig<5>) to turn on RX LDO indpendent of
0522      * pwdb controls from DSP_TAP10
0523      */
0524     bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0020);
0525 
0526     /* Remove references to channel 2 and 3 */
0527     bcm_phy_write_misc(phydev, 0x003b, 0x0002, 0x0000);
0528     bcm_phy_write_misc(phydev, 0x003b, 0x0003, 0x0000);
0529 
0530     /* Set cal_bypassb bit rxconfig<43> */
0531     bcm_phy_write_misc(phydev, 0x003a, 0x0003, 0x0800);
0532     udelay(2);
0533 
0534     /* Revert pwdb_override (rxconfig<5>) to 0 so that the RX pwr
0535      * is controlled by DSP.
0536      */
0537     bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0000);
0538 
0539     /* Drop LSB */
0540     rcalnewcode11d2 = (rcalnewcode11 & 0xfffe) / 2;
0541     tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0001);
0542     /* Clear bits [11:5] */
0543     tmp &= ~0xfe0;
0544     /* set txcfg_ch0<5>=1 (enable + set local rcal) */
0545     tmp |= 0x0020 | (rcalnewcode11d2 * 64);
0546     bcm_phy_write_misc(phydev, 0x003d, 0x0001, tmp);
0547     bcm_phy_write_misc(phydev, 0x003d, 0x0002, tmp);
0548 
0549     tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0000);
0550     /* set txcfg<45:44>=11 (enable Rextra + invert fullscaledetect)
0551      */
0552     tmp &= ~0x3000;
0553     tmp |= 0x3000;
0554     bcm_phy_write_misc(phydev, 0x003d, 0x0000, tmp);
0555 
0556     return 0;
0557 }
0558 
0559 static int bcm7xxx_16nm_ephy_config_init(struct phy_device *phydev)
0560 {
0561     int ret, val;
0562 
0563     ret = bcm7xxx_16nm_ephy_afe_config(phydev);
0564     if (ret)
0565         return ret;
0566 
0567     ret = bcm_phy_set_eee(phydev, true);
0568     if (ret)
0569         return ret;
0570 
0571     ret = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
0572     if (ret < 0)
0573         return ret;
0574 
0575     val = ret;
0576 
0577     /* Auto power down of DLL enabled,
0578      * TXC/RXC disabled during auto power down.
0579      */
0580     val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
0581     val |= BIT(8);
0582 
0583     ret = bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
0584     if (ret < 0)
0585         return ret;
0586 
0587     return bcm_phy_enable_apd(phydev, true);
0588 }
0589 
0590 static int bcm7xxx_16nm_ephy_resume(struct phy_device *phydev)
0591 {
0592     int ret;
0593 
0594     /* Re-apply workarounds coming out suspend/resume */
0595     ret = bcm7xxx_16nm_ephy_config_init(phydev);
0596     if (ret)
0597         return ret;
0598 
0599     return genphy_config_aneg(phydev);
0600 }
0601 
0602 #define MII_BCM7XXX_REG_INVALID 0xff
0603 
0604 static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
0605 {
0606     switch (regnum) {
0607     case MDIO_CTRL1:
0608         return MII_BCM7XXX_SHD_3_PCS_CTRL;
0609     case MDIO_STAT1:
0610         return MII_BCM7XXX_SHD_3_PCS_STATUS;
0611     case MDIO_PCS_EEE_ABLE:
0612         return MII_BCM7XXX_SHD_3_EEE_CAP;
0613     case MDIO_AN_EEE_ADV:
0614         return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
0615     case MDIO_AN_EEE_LPABLE:
0616         return MII_BCM7XXX_SHD_3_EEE_LP;
0617     case MDIO_PCS_EEE_WK_ERR:
0618         return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
0619     default:
0620         return MII_BCM7XXX_REG_INVALID;
0621     }
0622 }
0623 
0624 static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
0625 {
0626     return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
0627 }
0628 
0629 static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
0630                       int devnum, u16 regnum)
0631 {
0632     u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
0633     int ret;
0634 
0635     if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
0636         shd == MII_BCM7XXX_REG_INVALID)
0637         return -EOPNOTSUPP;
0638 
0639     /* set shadow mode 2 */
0640     ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
0641                  MII_BCM7XXX_SHD_MODE_2, 0);
0642     if (ret < 0)
0643         return ret;
0644 
0645     /* Access the desired shadow register address */
0646     ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
0647     if (ret < 0)
0648         goto reset_shadow_mode;
0649 
0650     ret = __phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
0651 
0652 reset_shadow_mode:
0653     /* reset shadow mode 2 */
0654     __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
0655                MII_BCM7XXX_SHD_MODE_2);
0656     return ret;
0657 }
0658 
0659 static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
0660                        int devnum, u16 regnum, u16 val)
0661 {
0662     u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
0663     int ret;
0664 
0665     if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
0666         shd == MII_BCM7XXX_REG_INVALID)
0667         return -EOPNOTSUPP;
0668 
0669     /* set shadow mode 2 */
0670     ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
0671                  MII_BCM7XXX_SHD_MODE_2, 0);
0672     if (ret < 0)
0673         return ret;
0674 
0675     /* Access the desired shadow register address */
0676     ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
0677     if (ret < 0)
0678         goto reset_shadow_mode;
0679 
0680     /* Write the desired value in the shadow register */
0681     __phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
0682 
0683 reset_shadow_mode:
0684     /* reset shadow mode 2 */
0685     return __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
0686                   MII_BCM7XXX_SHD_MODE_2);
0687 }
0688 
0689 static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
0690 {
0691     int ret;
0692 
0693     /* Re-apply workarounds coming out suspend/resume */
0694     ret = bcm7xxx_28nm_ephy_config_init(phydev);
0695     if (ret)
0696         return ret;
0697 
0698     return genphy_config_aneg(phydev);
0699 }
0700 
0701 static int bcm7xxx_config_init(struct phy_device *phydev)
0702 {
0703     int ret;
0704 
0705     /* Enable 64 clock MDIO */
0706     phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO);
0707     phy_read(phydev, MII_BCM7XXX_AUX_MODE);
0708 
0709     /* set shadow mode 2 */
0710     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
0711             MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
0712     if (ret < 0)
0713         return ret;
0714 
0715     /* set iddq_clkbias */
0716     phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
0717     udelay(10);
0718 
0719     /* reset iddq_clkbias */
0720     phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
0721 
0722     phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
0723 
0724     /* reset shadow mode 2 */
0725     ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2);
0726     if (ret < 0)
0727         return ret;
0728 
0729     return 0;
0730 }
0731 
0732 /* Workaround for putting the PHY in IDDQ mode, required
0733  * for all BCM7XXX 40nm and 65nm PHYs
0734  */
0735 static int bcm7xxx_suspend(struct phy_device *phydev)
0736 {
0737     int ret;
0738     static const struct bcm7xxx_regs {
0739         int reg;
0740         u16 value;
0741     } bcm7xxx_suspend_cfg[] = {
0742         { MII_BCM7XXX_TEST, 0x008b },
0743         { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 },
0744         { MII_BCM7XXX_100TX_DISC, 0x7000 },
0745         { MII_BCM7XXX_TEST, 0x000f },
0746         { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 },
0747         { MII_BCM7XXX_TEST, 0x000b },
0748     };
0749     unsigned int i;
0750 
0751     for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) {
0752         ret = phy_write(phydev,
0753                 bcm7xxx_suspend_cfg[i].reg,
0754                 bcm7xxx_suspend_cfg[i].value);
0755         if (ret)
0756             return ret;
0757     }
0758 
0759     return 0;
0760 }
0761 
0762 static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev,
0763                     struct ethtool_tunable *tuna,
0764                     void *data)
0765 {
0766     switch (tuna->id) {
0767     case ETHTOOL_PHY_DOWNSHIFT:
0768         return bcm_phy_downshift_get(phydev, (u8 *)data);
0769     default:
0770         return -EOPNOTSUPP;
0771     }
0772 }
0773 
0774 static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev,
0775                     struct ethtool_tunable *tuna,
0776                     const void *data)
0777 {
0778     u8 count = *(u8 *)data;
0779     int ret;
0780 
0781     switch (tuna->id) {
0782     case ETHTOOL_PHY_DOWNSHIFT:
0783         ret = bcm_phy_downshift_set(phydev, count);
0784         break;
0785     default:
0786         return -EOPNOTSUPP;
0787     }
0788 
0789     if (ret)
0790         return ret;
0791 
0792     /* Disable EEE advertisement since this prevents the PHY
0793      * from successfully linking up, trigger auto-negotiation restart
0794      * to let the MAC decide what to do.
0795      */
0796     ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
0797     if (ret)
0798         return ret;
0799 
0800     return genphy_restart_aneg(phydev);
0801 }
0802 
0803 static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
0804                        struct ethtool_stats *stats, u64 *data)
0805 {
0806     struct bcm7xxx_phy_priv *priv = phydev->priv;
0807 
0808     bcm_phy_get_stats(phydev, priv->stats, stats, data);
0809 }
0810 
0811 static int bcm7xxx_28nm_probe(struct phy_device *phydev)
0812 {
0813     struct bcm7xxx_phy_priv *priv;
0814     int ret = 0;
0815 
0816     priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
0817     if (!priv)
0818         return -ENOMEM;
0819 
0820     phydev->priv = priv;
0821 
0822     priv->stats = devm_kcalloc(&phydev->mdio.dev,
0823                    bcm_phy_get_sset_count(phydev), sizeof(u64),
0824                    GFP_KERNEL);
0825     if (!priv->stats)
0826         return -ENOMEM;
0827 
0828     priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL);
0829     if (IS_ERR(priv->clk))
0830         return PTR_ERR(priv->clk);
0831 
0832     ret = clk_prepare_enable(priv->clk);
0833     if (ret)
0834         return ret;
0835 
0836     /* Dummy read to a register to workaround an issue upon reset where the
0837      * internal inverter may not allow the first MDIO transaction to pass
0838      * the MDIO management controller and make us return 0xffff for such
0839      * reads. This is needed to ensure that any subsequent reads to the
0840      * PHY will succeed.
0841      */
0842     phy_read(phydev, MII_BMSR);
0843 
0844     return ret;
0845 }
0846 
0847 static void bcm7xxx_28nm_remove(struct phy_device *phydev)
0848 {
0849     struct bcm7xxx_phy_priv *priv = phydev->priv;
0850 
0851     clk_disable_unprepare(priv->clk);
0852 }
0853 
0854 #define BCM7XXX_28NM_GPHY(_oui, _name)                  \
0855 {                                   \
0856     .phy_id     = (_oui),                   \
0857     .phy_id_mask    = 0xfffffff0,                   \
0858     .name       = _name,                    \
0859     /* PHY_GBIT_FEATURES */                     \
0860     .flags      = PHY_IS_INTERNAL,              \
0861     .config_init    = bcm7xxx_28nm_config_init,         \
0862     .resume     = bcm7xxx_28nm_resume,              \
0863     .get_tunable    = bcm7xxx_28nm_get_tunable,         \
0864     .set_tunable    = bcm7xxx_28nm_set_tunable,         \
0865     .get_sset_count = bcm_phy_get_sset_count,           \
0866     .get_strings    = bcm_phy_get_strings,              \
0867     .get_stats  = bcm7xxx_28nm_get_phy_stats,           \
0868     .probe      = bcm7xxx_28nm_probe,               \
0869     .remove     = bcm7xxx_28nm_remove,              \
0870 }
0871 
0872 #define BCM7XXX_28NM_EPHY(_oui, _name)                  \
0873 {                                   \
0874     .phy_id     = (_oui),                   \
0875     .phy_id_mask    = 0xfffffff0,                   \
0876     .name       = _name,                    \
0877     /* PHY_BASIC_FEATURES */                    \
0878     .flags      = PHY_IS_INTERNAL,              \
0879     .config_init    = bcm7xxx_28nm_ephy_config_init,        \
0880     .resume     = bcm7xxx_28nm_ephy_resume,         \
0881     .get_sset_count = bcm_phy_get_sset_count,           \
0882     .get_strings    = bcm_phy_get_strings,              \
0883     .get_stats  = bcm7xxx_28nm_get_phy_stats,           \
0884     .probe      = bcm7xxx_28nm_probe,               \
0885     .remove     = bcm7xxx_28nm_remove,              \
0886     .read_mmd   = bcm7xxx_28nm_ephy_read_mmd,           \
0887     .write_mmd  = bcm7xxx_28nm_ephy_write_mmd,          \
0888 }
0889 
0890 #define BCM7XXX_40NM_EPHY(_oui, _name)                  \
0891 {                                   \
0892     .phy_id         = (_oui),                   \
0893     .phy_id_mask    = 0xfffffff0,                   \
0894     .name           = _name,                    \
0895     /* PHY_BASIC_FEATURES */                    \
0896     .flags          = PHY_IS_INTERNAL,              \
0897     .soft_reset = genphy_soft_reset,                \
0898     .config_init    = bcm7xxx_config_init,              \
0899     .suspend        = bcm7xxx_suspend,              \
0900     .resume         = bcm7xxx_config_init,              \
0901 }
0902 
0903 #define BCM7XXX_16NM_EPHY(_oui, _name)                  \
0904 {                                   \
0905     .phy_id     = (_oui),                   \
0906     .phy_id_mask    = 0xfffffff0,                   \
0907     .name       = _name,                    \
0908     /* PHY_BASIC_FEATURES */                    \
0909     .flags      = PHY_IS_INTERNAL,              \
0910     .probe      = bcm7xxx_28nm_probe,               \
0911     .remove     = bcm7xxx_28nm_remove,              \
0912     .config_init    = bcm7xxx_16nm_ephy_config_init,        \
0913     .config_aneg    = genphy_config_aneg,               \
0914     .read_status    = genphy_read_status,               \
0915     .resume     = bcm7xxx_16nm_ephy_resume,         \
0916 }
0917 
0918 static struct phy_driver bcm7xxx_driver[] = {
0919     BCM7XXX_28NM_EPHY(PHY_ID_BCM72113, "Broadcom BCM72113"),
0920     BCM7XXX_28NM_EPHY(PHY_ID_BCM72116, "Broadcom BCM72116"),
0921     BCM7XXX_16NM_EPHY(PHY_ID_BCM72165, "Broadcom BCM72165"),
0922     BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
0923     BCM7XXX_28NM_EPHY(PHY_ID_BCM7255, "Broadcom BCM7255"),
0924     BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"),
0925     BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"),
0926     BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"),
0927     BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
0928     BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
0929     BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
0930     BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"),
0931     BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
0932     BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"),
0933     BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"),
0934     BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"),
0935     BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"),
0936     BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"),
0937     BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"),
0938     BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"),
0939     BCM7XXX_16NM_EPHY(PHY_ID_BCM7712, "Broadcom BCM7712"),
0940 };
0941 
0942 static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
0943     { PHY_ID_BCM72113, 0xfffffff0 },
0944     { PHY_ID_BCM72116, 0xfffffff0, },
0945     { PHY_ID_BCM72165, 0xfffffff0, },
0946     { PHY_ID_BCM7250, 0xfffffff0, },
0947     { PHY_ID_BCM7255, 0xfffffff0, },
0948     { PHY_ID_BCM7260, 0xfffffff0, },
0949     { PHY_ID_BCM7268, 0xfffffff0, },
0950     { PHY_ID_BCM7271, 0xfffffff0, },
0951     { PHY_ID_BCM7278, 0xfffffff0, },
0952     { PHY_ID_BCM7364, 0xfffffff0, },
0953     { PHY_ID_BCM7366, 0xfffffff0, },
0954     { PHY_ID_BCM7346, 0xfffffff0, },
0955     { PHY_ID_BCM7362, 0xfffffff0, },
0956     { PHY_ID_BCM7425, 0xfffffff0, },
0957     { PHY_ID_BCM7429, 0xfffffff0, },
0958     { PHY_ID_BCM74371, 0xfffffff0, },
0959     { PHY_ID_BCM7439, 0xfffffff0, },
0960     { PHY_ID_BCM7435, 0xfffffff0, },
0961     { PHY_ID_BCM7445, 0xfffffff0, },
0962     { PHY_ID_BCM7712, 0xfffffff0, },
0963     { }
0964 };
0965 
0966 module_phy_driver(bcm7xxx_driver);
0967 
0968 MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl);
0969 
0970 MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver");
0971 MODULE_LICENSE("GPL");
0972 MODULE_AUTHOR("Broadcom Corporation");