linux/drivers/net/phy/bcm7xxx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Broadcom BCM7xxx internal transceivers support.
   4 *
   5 * Copyright (C) 2014-2017 Broadcom
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/phy.h>
  10#include <linux/delay.h>
  11#include "bcm-phy-lib.h"
  12#include <linux/bitops.h>
  13#include <linux/brcmphy.h>
  14#include <linux/clk.h>
  15#include <linux/mdio.h>
  16
  17/* Broadcom BCM7xxx internal PHY registers */
  18
  19/* EPHY only register definitions */
  20#define MII_BCM7XXX_100TX_AUX_CTL       0x10
  21#define MII_BCM7XXX_100TX_FALSE_CAR     0x13
  22#define MII_BCM7XXX_100TX_DISC          0x14
  23#define MII_BCM7XXX_AUX_MODE            0x1d
  24#define  MII_BCM7XXX_64CLK_MDIO         BIT(12)
  25#define MII_BCM7XXX_TEST                0x1f
  26#define  MII_BCM7XXX_SHD_MODE_2         BIT(2)
  27#define MII_BCM7XXX_SHD_2_ADDR_CTRL     0xe
  28#define MII_BCM7XXX_SHD_2_CTRL_STAT     0xf
  29#define MII_BCM7XXX_SHD_2_BIAS_TRIM     0x1a
  30#define MII_BCM7XXX_SHD_3_PCS_CTRL      0x0
  31#define MII_BCM7XXX_SHD_3_PCS_STATUS    0x1
  32#define MII_BCM7XXX_SHD_3_EEE_CAP       0x2
  33#define MII_BCM7XXX_SHD_3_AN_EEE_ADV    0x3
  34#define MII_BCM7XXX_SHD_3_EEE_LP        0x4
  35#define MII_BCM7XXX_SHD_3_EEE_WK_ERR    0x5
  36#define MII_BCM7XXX_SHD_3_PCS_CTRL_2    0x6
  37#define  MII_BCM7XXX_PCS_CTRL_2_DEF     0x4400
  38#define MII_BCM7XXX_SHD_3_AN_STAT       0xb
  39#define  MII_BCM7XXX_AN_NULL_MSG_EN     BIT(0)
  40#define  MII_BCM7XXX_AN_EEE_EN          BIT(1)
  41#define MII_BCM7XXX_SHD_3_EEE_THRESH    0xe
  42#define  MII_BCM7XXX_EEE_THRESH_DEF     0x50
  43#define MII_BCM7XXX_SHD_3_TL4           0x23
  44#define  MII_BCM7XXX_TL4_RST_MSK        (BIT(2) | BIT(1))
  45
  46struct bcm7xxx_phy_priv {
  47        u64     *stats;
  48        struct clk *clk;
  49};
  50
  51static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
  52{
  53        /* AFE_RXCONFIG_0 */
  54        bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
  55
  56        /* AFE_RXCONFIG_1 */
  57        bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
  58
  59        /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
  60        bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
  61
  62        /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
  63        bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
  64
  65        /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
  66        bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
  67
  68        /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
  69        bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
  70
  71        /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
  72        bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
  73
  74        /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
  75         * offset for HT=0 code
  76         */
  77        bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
  78
  79        /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
  80        phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
  81
  82        /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
  83        bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
  84
  85        /* Reset R_CAL/RC_CAL engine */
  86        bcm_phy_r_rc_cal_reset(phydev);
  87
  88        return 0;
  89}
  90
  91static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
  92{
  93        /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
  94        bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
  95
  96        /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
  97        bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
  98
  99        /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
 100        bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
 101
 102        /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
 103         * offset for HT=0 code
 104         */
 105        bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
 106
 107        /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
 108        phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
 109
 110        /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
 111        bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
 112
 113        /* Reset R_CAL/RC_CAL engine */
 114        bcm_phy_r_rc_cal_reset(phydev);
 115
 116        return 0;
 117}
 118
 119static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev)
 120{
 121        /* +1 RC_CAL codes for RL centering for both LT and HT conditions */
 122        bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
 123
 124        /* Cut master bias current by 2% to compensate for RC_CAL offset */
 125        bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
 126
 127        /* Improve hybrid leakage */
 128        bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
 129
 130        /* Change rx_on_tune 8 to 0xf */
 131        bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
 132
 133        /* Change 100Tx EEE bandwidth */
 134        bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
 135
 136        /* Enable ffe zero detection for Vitesse interoperability */
 137        bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015);
 138
 139        bcm_phy_r_rc_cal_reset(phydev);
 140
 141        return 0;
 142}
 143
 144static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
 145{
 146        u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
 147        u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
 148        u8 count;
 149        int ret = 0;
 150
 151        /* Newer devices have moved the revision information back into a
 152         * standard location in MII_PHYS_ID[23]
 153         */
 154        if (rev == 0)
 155                rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
 156
 157        pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
 158                     phydev_name(phydev), phydev->drv->name, rev, patch);
 159
 160        /* Dummy read to a register to workaround an issue upon reset where the
 161         * internal inverter may not allow the first MDIO transaction to pass
 162         * the MDIO management controller and make us return 0xffff for such
 163         * reads.
 164         */
 165        phy_read(phydev, MII_BMSR);
 166
 167        switch (rev) {
 168        case 0xa0:
 169        case 0xb0:
 170                ret = bcm_phy_28nm_a0b0_afe_config_init(phydev);
 171                break;
 172        case 0xd0:
 173                ret = bcm7xxx_28nm_d0_afe_config_init(phydev);
 174                break;
 175        case 0xe0:
 176        case 0xf0:
 177        /* Rev G0 introduces a roll over */
 178        case 0x10:
 179                ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
 180                break;
 181        case 0x01:
 182                ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
 183                break;
 184        default:
 185                break;
 186        }
 187
 188        if (ret)
 189                return ret;
 190
 191        ret =  bcm_phy_enable_jumbo(phydev);
 192        if (ret)
 193                return ret;
 194
 195        ret = bcm_phy_downshift_get(phydev, &count);
 196        if (ret)
 197                return ret;
 198
 199        /* Only enable EEE if Wirespeed/downshift is disabled */
 200        ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
 201        if (ret)
 202                return ret;
 203
 204        return bcm_phy_enable_apd(phydev, true);
 205}
 206
 207static int bcm7xxx_28nm_resume(struct phy_device *phydev)
 208{
 209        int ret;
 210
 211        /* Re-apply workarounds coming out suspend/resume */
 212        ret = bcm7xxx_28nm_config_init(phydev);
 213        if (ret)
 214                return ret;
 215
 216        /* 28nm Gigabit PHYs come out of reset without any half-duplex
 217         * or "hub" compliant advertised mode, fix that. This does not
 218         * cause any problems with the PHY library since genphy_config_aneg()
 219         * gracefully handles auto-negotiated and forced modes.
 220         */
 221        return genphy_config_aneg(phydev);
 222}
 223
 224static int __phy_set_clr_bits(struct phy_device *dev, int location,
 225                              int set_mask, int clr_mask)
 226{
 227        int v, ret;
 228
 229        v = __phy_read(dev, location);
 230        if (v < 0)
 231                return v;
 232
 233        v &= ~clr_mask;
 234        v |= set_mask;
 235
 236        ret = __phy_write(dev, location, v);
 237        if (ret < 0)
 238                return ret;
 239
 240        return v;
 241}
 242
 243static int phy_set_clr_bits(struct phy_device *dev, int location,
 244                            int set_mask, int clr_mask)
 245{
 246        int ret;
 247
 248        mutex_lock(&dev->mdio.bus->mdio_lock);
 249        ret = __phy_set_clr_bits(dev, location, set_mask, clr_mask);
 250        mutex_unlock(&dev->mdio.bus->mdio_lock);
 251
 252        return ret;
 253}
 254
 255static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
 256{
 257        int ret;
 258
 259        /* set shadow mode 2 */
 260        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
 261                               MII_BCM7XXX_SHD_MODE_2, 0);
 262        if (ret < 0)
 263                return ret;
 264
 265        /* Set current trim values INT_trim = -1, Ext_trim =0 */
 266        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
 267        if (ret < 0)
 268                goto reset_shadow_mode;
 269
 270        /* Cal reset */
 271        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
 272                        MII_BCM7XXX_SHD_3_TL4);
 273        if (ret < 0)
 274                goto reset_shadow_mode;
 275        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
 276                               MII_BCM7XXX_TL4_RST_MSK, 0);
 277        if (ret < 0)
 278                goto reset_shadow_mode;
 279
 280        /* Cal reset disable */
 281        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
 282                        MII_BCM7XXX_SHD_3_TL4);
 283        if (ret < 0)
 284                goto reset_shadow_mode;
 285        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
 286                               0, MII_BCM7XXX_TL4_RST_MSK);
 287        if (ret < 0)
 288                goto reset_shadow_mode;
 289
 290reset_shadow_mode:
 291        /* reset shadow mode 2 */
 292        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
 293                               MII_BCM7XXX_SHD_MODE_2);
 294        if (ret < 0)
 295                return ret;
 296
 297        return 0;
 298}
 299
 300/* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */
 301static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
 302{
 303        int ret;
 304
 305        /* set shadow mode 1 */
 306        ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST,
 307                               MII_BRCM_FET_BT_SRE, 0);
 308        if (ret < 0)
 309                return ret;
 310
 311        /* Enable auto-power down */
 312        ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
 313                               MII_BRCM_FET_SHDW_AS2_APDE, 0);
 314        if (ret < 0)
 315                return ret;
 316
 317        /* reset shadow mode 1 */
 318        ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0,
 319                               MII_BRCM_FET_BT_SRE);
 320        if (ret < 0)
 321                return ret;
 322
 323        return 0;
 324}
 325
 326static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev)
 327{
 328        int ret;
 329
 330        /* set shadow mode 2 */
 331        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
 332                               MII_BCM7XXX_SHD_MODE_2, 0);
 333        if (ret < 0)
 334                return ret;
 335
 336        /* Advertise supported modes */
 337        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
 338                        MII_BCM7XXX_SHD_3_AN_EEE_ADV);
 339        if (ret < 0)
 340                goto reset_shadow_mode;
 341        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
 342                        MDIO_EEE_100TX);
 343        if (ret < 0)
 344                goto reset_shadow_mode;
 345
 346        /* Restore Defaults */
 347        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
 348                        MII_BCM7XXX_SHD_3_PCS_CTRL_2);
 349        if (ret < 0)
 350                goto reset_shadow_mode;
 351        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
 352                        MII_BCM7XXX_PCS_CTRL_2_DEF);
 353        if (ret < 0)
 354                goto reset_shadow_mode;
 355
 356        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
 357                        MII_BCM7XXX_SHD_3_EEE_THRESH);
 358        if (ret < 0)
 359                goto reset_shadow_mode;
 360        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
 361                        MII_BCM7XXX_EEE_THRESH_DEF);
 362        if (ret < 0)
 363                goto reset_shadow_mode;
 364
 365        /* Enable EEE autonegotiation */
 366        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL,
 367                        MII_BCM7XXX_SHD_3_AN_STAT);
 368        if (ret < 0)
 369                goto reset_shadow_mode;
 370        ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT,
 371                        (MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN));
 372        if (ret < 0)
 373                goto reset_shadow_mode;
 374
 375reset_shadow_mode:
 376        /* reset shadow mode 2 */
 377        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
 378                               MII_BCM7XXX_SHD_MODE_2);
 379        if (ret < 0)
 380                return ret;
 381
 382        /* Restart autoneg */
 383        phy_write(phydev, MII_BMCR,
 384                  (BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART));
 385
 386        return 0;
 387}
 388
 389static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
 390{
 391        u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
 392        int ret = 0;
 393
 394        pr_info_once("%s: %s PHY revision: 0x%02x\n",
 395                     phydev_name(phydev), phydev->drv->name, rev);
 396
 397        /* Dummy read to a register to workaround a possible issue upon reset
 398         * where the internal inverter may not allow the first MDIO transaction
 399         * to pass the MDIO management controller and make us return 0xffff for
 400         * such reads.
 401         */
 402        phy_read(phydev, MII_BMSR);
 403
 404        /* Apply AFE software work-around if necessary */
 405        if (rev == 0x01) {
 406                ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev);
 407                if (ret)
 408                        return ret;
 409        }
 410
 411        ret = bcm7xxx_28nm_ephy_eee_enable(phydev);
 412        if (ret)
 413                return ret;
 414
 415        return bcm7xxx_28nm_ephy_apd_enable(phydev);
 416}
 417
 418static int bcm7xxx_16nm_ephy_afe_config(struct phy_device *phydev)
 419{
 420        int tmp, rcalcode, rcalnewcodelp, rcalnewcode11, rcalnewcode11d2;
 421
 422        /* Reset PHY */
 423        tmp = genphy_soft_reset(phydev);
 424        if (tmp)
 425                return tmp;
 426
 427        /* Reset AFE and PLL */
 428        bcm_phy_write_exp_sel(phydev, 0x0003, 0x0006);
 429        /* Clear reset */
 430        bcm_phy_write_exp_sel(phydev, 0x0003, 0x0000);
 431
 432        /* Write PLL/AFE control register to select 54MHz crystal */
 433        bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0000);
 434        bcm_phy_write_misc(phydev, 0x0031, 0x0000, 0x044a);
 435
 436        /* Change Ka,Kp,Ki to pdiv=1 */
 437        bcm_phy_write_misc(phydev, 0x0033, 0x0002, 0x71a1);
 438        /* Configuration override */
 439        bcm_phy_write_misc(phydev, 0x0033, 0x0001, 0x8000);
 440
 441        /* Change PLL_NDIV and PLL_NUDGE */
 442        bcm_phy_write_misc(phydev, 0x0031, 0x0001, 0x2f68);
 443        bcm_phy_write_misc(phydev, 0x0031, 0x0002, 0x0000);
 444
 445        /* Reference frequency is 54Mhz, config_mode[15:14] = 3 (low
 446         * phase)
 447         */
 448        bcm_phy_write_misc(phydev, 0x0030, 0x0003, 0xc036);
 449
 450        /* Initialize bypass mode */
 451        bcm_phy_write_misc(phydev, 0x0032, 0x0003, 0x0000);
 452        /* Bypass code, default: VCOCLK enabled */
 453        bcm_phy_write_misc(phydev, 0x0033, 0x0000, 0x0002);
 454        /* LDOs at default setting */
 455        bcm_phy_write_misc(phydev, 0x0030, 0x0002, 0x01c0);
 456        /* Release PLL reset */
 457        bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0001);
 458
 459        /* Bandgap curvature correction to correct default */
 460        bcm_phy_write_misc(phydev, 0x0038, 0x0000, 0x0010);
 461
 462        /* Run RCAL */
 463        bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x0038);
 464        bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x003b);
 465        udelay(2);
 466        bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x003f);
 467        mdelay(5);
 468
 469        /* AFE_CAL_CONFIG_0, Vref=1000, Target=10, averaging enabled */
 470        bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x1c82);
 471        /* AFE_CAL_CONFIG_0, no reset and analog powerup */
 472        bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e82);
 473        udelay(2);
 474        /* AFE_CAL_CONFIG_0, start calibration */
 475        bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f82);
 476        udelay(100);
 477        /* AFE_CAL_CONFIG_0, clear start calibration, set HiBW */
 478        bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e86);
 479        udelay(2);
 480        /* AFE_CAL_CONFIG_0, start calibration with hi BW mode set */
 481        bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f86);
 482        udelay(100);
 483
 484        /* Adjust 10BT amplitude additional +7% and 100BT +2% */
 485        bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7ea);
 486        /* Adjust 1G mode amplitude and 1G testmode1 */
 487        bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0);
 488
 489        /* Read CORE_EXPA9 */
 490        tmp = bcm_phy_read_exp(phydev, 0x00a9);
 491        /* CORE_EXPA9[6:1] is rcalcode[5:0] */
 492        rcalcode = (tmp & 0x7e) / 2;
 493        /* Correct RCAL code + 1 is -1% rprogr, LP: +16 */
 494        rcalnewcodelp = rcalcode + 16;
 495        /* Correct RCAL code + 1 is -15 rprogr, 11: +10 */
 496        rcalnewcode11 = rcalcode + 10;
 497        /* Saturate if necessary */
 498        if (rcalnewcodelp > 0x3f)
 499                rcalnewcodelp = 0x3f;
 500        if (rcalnewcode11 > 0x3f)
 501                rcalnewcode11 = 0x3f;
 502        /* REXT=1 BYP=1 RCAL_st1<5:0>=new rcal code */
 503        tmp = 0x00f8 + rcalnewcodelp * 256;
 504        /* Program into AFE_CAL_CONFIG_2 */
 505        bcm_phy_write_misc(phydev, 0x0039, 0x0003, tmp);
 506        /* AFE_BIAS_CONFIG_0 10BT bias code (Bias: E4) */
 507        bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7e4);
 508        /* invert adc clock output and 'adc refp ldo current To correct
 509         * default
 510         */
 511        bcm_phy_write_misc(phydev, 0x003b, 0x0000, 0x8002);
 512        /* 100BT stair case, high BW, 1G stair case, alternate encode */
 513        bcm_phy_write_misc(phydev, 0x003c, 0x0003, 0xf882);
 514        /* 1000BT DAC transition method per Erol, bits[32], DAC Shuffle
 515         * sequence 1 + 10BT imp adjust bits
 516         */
 517        bcm_phy_write_misc(phydev, 0x003d, 0x0000, 0x3201);
 518        /* Non-overlap fix */
 519        bcm_phy_write_misc(phydev, 0x003a, 0x0002, 0x0c00);
 520
 521        /* pwdb override (rxconfig<5>) to turn on RX LDO indpendent of
 522         * pwdb controls from DSP_TAP10
 523         */
 524        bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0020);
 525
 526        /* Remove references to channel 2 and 3 */
 527        bcm_phy_write_misc(phydev, 0x003b, 0x0002, 0x0000);
 528        bcm_phy_write_misc(phydev, 0x003b, 0x0003, 0x0000);
 529
 530        /* Set cal_bypassb bit rxconfig<43> */
 531        bcm_phy_write_misc(phydev, 0x003a, 0x0003, 0x0800);
 532        udelay(2);
 533
 534        /* Revert pwdb_override (rxconfig<5>) to 0 so that the RX pwr
 535         * is controlled by DSP.
 536         */
 537        bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0000);
 538
 539        /* Drop LSB */
 540        rcalnewcode11d2 = (rcalnewcode11 & 0xfffe) / 2;
 541        tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0001);
 542        /* Clear bits [11:5] */
 543        tmp &= ~0xfe0;
 544        /* set txcfg_ch0<5>=1 (enable + set local rcal) */
 545        tmp |= 0x0020 | (rcalnewcode11d2 * 64);
 546        bcm_phy_write_misc(phydev, 0x003d, 0x0001, tmp);
 547        bcm_phy_write_misc(phydev, 0x003d, 0x0002, tmp);
 548
 549        tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0000);
 550        /* set txcfg<45:44>=11 (enable Rextra + invert fullscaledetect)
 551         */
 552        tmp &= ~0x3000;
 553        tmp |= 0x3000;
 554        bcm_phy_write_misc(phydev, 0x003d, 0x0000, tmp);
 555
 556        return 0;
 557}
 558
 559static int bcm7xxx_16nm_ephy_config_init(struct phy_device *phydev)
 560{
 561        int ret, val;
 562
 563        ret = bcm7xxx_16nm_ephy_afe_config(phydev);
 564        if (ret)
 565                return ret;
 566
 567        ret = bcm_phy_set_eee(phydev, true);
 568        if (ret)
 569                return ret;
 570
 571        ret = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
 572        if (ret < 0)
 573                return ret;
 574
 575        val = ret;
 576
 577        /* Auto power down of DLL enabled,
 578         * TXC/RXC disabled during auto power down.
 579         */
 580        val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
 581        val |= BIT(8);
 582
 583        ret = bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
 584        if (ret < 0)
 585                return ret;
 586
 587        return bcm_phy_enable_apd(phydev, true);
 588}
 589
 590static int bcm7xxx_16nm_ephy_resume(struct phy_device *phydev)
 591{
 592        int ret;
 593
 594        /* Re-apply workarounds coming out suspend/resume */
 595        ret = bcm7xxx_16nm_ephy_config_init(phydev);
 596        if (ret)
 597                return ret;
 598
 599        return genphy_config_aneg(phydev);
 600}
 601
 602#define MII_BCM7XXX_REG_INVALID 0xff
 603
 604static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
 605{
 606        switch (regnum) {
 607        case MDIO_CTRL1:
 608                return MII_BCM7XXX_SHD_3_PCS_CTRL;
 609        case MDIO_STAT1:
 610                return MII_BCM7XXX_SHD_3_PCS_STATUS;
 611        case MDIO_PCS_EEE_ABLE:
 612                return MII_BCM7XXX_SHD_3_EEE_CAP;
 613        case MDIO_AN_EEE_ADV:
 614                return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
 615        case MDIO_AN_EEE_LPABLE:
 616                return MII_BCM7XXX_SHD_3_EEE_LP;
 617        case MDIO_PCS_EEE_WK_ERR:
 618                return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
 619        default:
 620                return MII_BCM7XXX_REG_INVALID;
 621        }
 622}
 623
 624static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
 625{
 626        return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
 627}
 628
 629static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
 630                                      int devnum, u16 regnum)
 631{
 632        u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
 633        int ret;
 634
 635        if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
 636            shd == MII_BCM7XXX_REG_INVALID)
 637                return -EOPNOTSUPP;
 638
 639        /* set shadow mode 2 */
 640        ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
 641                                 MII_BCM7XXX_SHD_MODE_2, 0);
 642        if (ret < 0)
 643                return ret;
 644
 645        /* Access the desired shadow register address */
 646        ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
 647        if (ret < 0)
 648                goto reset_shadow_mode;
 649
 650        ret = __phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
 651
 652reset_shadow_mode:
 653        /* reset shadow mode 2 */
 654        __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
 655                           MII_BCM7XXX_SHD_MODE_2);
 656        return ret;
 657}
 658
 659static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
 660                                       int devnum, u16 regnum, u16 val)
 661{
 662        u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
 663        int ret;
 664
 665        if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
 666            shd == MII_BCM7XXX_REG_INVALID)
 667                return -EOPNOTSUPP;
 668
 669        /* set shadow mode 2 */
 670        ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
 671                                 MII_BCM7XXX_SHD_MODE_2, 0);
 672        if (ret < 0)
 673                return ret;
 674
 675        /* Access the desired shadow register address */
 676        ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
 677        if (ret < 0)
 678                goto reset_shadow_mode;
 679
 680        /* Write the desired value in the shadow register */
 681        __phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
 682
 683reset_shadow_mode:
 684        /* reset shadow mode 2 */
 685        return __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
 686                                  MII_BCM7XXX_SHD_MODE_2);
 687}
 688
 689static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
 690{
 691        int ret;
 692
 693        /* Re-apply workarounds coming out suspend/resume */
 694        ret = bcm7xxx_28nm_ephy_config_init(phydev);
 695        if (ret)
 696                return ret;
 697
 698        return genphy_config_aneg(phydev);
 699}
 700
 701static int bcm7xxx_config_init(struct phy_device *phydev)
 702{
 703        int ret;
 704
 705        /* Enable 64 clock MDIO */
 706        phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO);
 707        phy_read(phydev, MII_BCM7XXX_AUX_MODE);
 708
 709        /* set shadow mode 2 */
 710        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
 711                        MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
 712        if (ret < 0)
 713                return ret;
 714
 715        /* set iddq_clkbias */
 716        phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
 717        udelay(10);
 718
 719        /* reset iddq_clkbias */
 720        phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
 721
 722        phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
 723
 724        /* reset shadow mode 2 */
 725        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2);
 726        if (ret < 0)
 727                return ret;
 728
 729        return 0;
 730}
 731
 732/* Workaround for putting the PHY in IDDQ mode, required
 733 * for all BCM7XXX 40nm and 65nm PHYs
 734 */
 735static int bcm7xxx_suspend(struct phy_device *phydev)
 736{
 737        int ret;
 738        static const struct bcm7xxx_regs {
 739                int reg;
 740                u16 value;
 741        } bcm7xxx_suspend_cfg[] = {
 742                { MII_BCM7XXX_TEST, 0x008b },
 743                { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 },
 744                { MII_BCM7XXX_100TX_DISC, 0x7000 },
 745                { MII_BCM7XXX_TEST, 0x000f },
 746                { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 },
 747                { MII_BCM7XXX_TEST, 0x000b },
 748        };
 749        unsigned int i;
 750
 751        for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) {
 752                ret = phy_write(phydev,
 753                                bcm7xxx_suspend_cfg[i].reg,
 754                                bcm7xxx_suspend_cfg[i].value);
 755                if (ret)
 756                        return ret;
 757        }
 758
 759        return 0;
 760}
 761
 762static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev,
 763                                    struct ethtool_tunable *tuna,
 764                                    void *data)
 765{
 766        switch (tuna->id) {
 767        case ETHTOOL_PHY_DOWNSHIFT:
 768                return bcm_phy_downshift_get(phydev, (u8 *)data);
 769        default:
 770                return -EOPNOTSUPP;
 771        }
 772}
 773
 774static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev,
 775                                    struct ethtool_tunable *tuna,
 776                                    const void *data)
 777{
 778        u8 count = *(u8 *)data;
 779        int ret;
 780
 781        switch (tuna->id) {
 782        case ETHTOOL_PHY_DOWNSHIFT:
 783                ret = bcm_phy_downshift_set(phydev, count);
 784                break;
 785        default:
 786                return -EOPNOTSUPP;
 787        }
 788
 789        if (ret)
 790                return ret;
 791
 792        /* Disable EEE advertisement since this prevents the PHY
 793         * from successfully linking up, trigger auto-negotiation restart
 794         * to let the MAC decide what to do.
 795         */
 796        ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE);
 797        if (ret)
 798                return ret;
 799
 800        return genphy_restart_aneg(phydev);
 801}
 802
 803static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev,
 804                                       struct ethtool_stats *stats, u64 *data)
 805{
 806        struct bcm7xxx_phy_priv *priv = phydev->priv;
 807
 808        bcm_phy_get_stats(phydev, priv->stats, stats, data);
 809}
 810
 811static int bcm7xxx_28nm_probe(struct phy_device *phydev)
 812{
 813        struct bcm7xxx_phy_priv *priv;
 814        int ret = 0;
 815
 816        priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
 817        if (!priv)
 818                return -ENOMEM;
 819
 820        phydev->priv = priv;
 821
 822        priv->stats = devm_kcalloc(&phydev->mdio.dev,
 823                                   bcm_phy_get_sset_count(phydev), sizeof(u64),
 824                                   GFP_KERNEL);
 825        if (!priv->stats)
 826                return -ENOMEM;
 827
 828        priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL);
 829        if (IS_ERR(priv->clk))
 830                return PTR_ERR(priv->clk);
 831
 832        ret = clk_prepare_enable(priv->clk);
 833        if (ret)
 834                return ret;
 835
 836        /* Dummy read to a register to workaround an issue upon reset where the
 837         * internal inverter may not allow the first MDIO transaction to pass
 838         * the MDIO management controller and make us return 0xffff for such
 839         * reads. This is needed to ensure that any subsequent reads to the
 840         * PHY will succeed.
 841         */
 842        phy_read(phydev, MII_BMSR);
 843
 844        return ret;
 845}
 846
 847static void bcm7xxx_28nm_remove(struct phy_device *phydev)
 848{
 849        struct bcm7xxx_phy_priv *priv = phydev->priv;
 850
 851        clk_disable_unprepare(priv->clk);
 852}
 853
 854#define BCM7XXX_28NM_GPHY(_oui, _name)                                  \
 855{                                                                       \
 856        .phy_id         = (_oui),                                       \
 857        .phy_id_mask    = 0xfffffff0,                                   \
 858        .name           = _name,                                        \
 859        /* PHY_GBIT_FEATURES */                                         \
 860        .flags          = PHY_IS_INTERNAL,                              \
 861        .config_init    = bcm7xxx_28nm_config_init,                     \
 862        .resume         = bcm7xxx_28nm_resume,                          \
 863        .get_tunable    = bcm7xxx_28nm_get_tunable,                     \
 864        .set_tunable    = bcm7xxx_28nm_set_tunable,                     \
 865        .get_sset_count = bcm_phy_get_sset_count,                       \
 866        .get_strings    = bcm_phy_get_strings,                          \
 867        .get_stats      = bcm7xxx_28nm_get_phy_stats,                   \
 868        .probe          = bcm7xxx_28nm_probe,                           \
 869        .remove         = bcm7xxx_28nm_remove,                          \
 870}
 871
 872#define BCM7XXX_28NM_EPHY(_oui, _name)                                  \
 873{                                                                       \
 874        .phy_id         = (_oui),                                       \
 875        .phy_id_mask    = 0xfffffff0,                                   \
 876        .name           = _name,                                        \
 877        /* PHY_BASIC_FEATURES */                                        \
 878        .flags          = PHY_IS_INTERNAL,                              \
 879        .config_init    = bcm7xxx_28nm_ephy_config_init,                \
 880        .resume         = bcm7xxx_28nm_ephy_resume,                     \
 881        .get_sset_count = bcm_phy_get_sset_count,                       \
 882        .get_strings    = bcm_phy_get_strings,                          \
 883        .get_stats      = bcm7xxx_28nm_get_phy_stats,                   \
 884        .probe          = bcm7xxx_28nm_probe,                           \
 885        .remove         = bcm7xxx_28nm_remove,                          \
 886        .read_mmd       = bcm7xxx_28nm_ephy_read_mmd,                   \
 887        .write_mmd      = bcm7xxx_28nm_ephy_write_mmd,                  \
 888}
 889
 890#define BCM7XXX_40NM_EPHY(_oui, _name)                                  \
 891{                                                                       \
 892        .phy_id         = (_oui),                                       \
 893        .phy_id_mask    = 0xfffffff0,                                   \
 894        .name           = _name,                                        \
 895        /* PHY_BASIC_FEATURES */                                        \
 896        .flags          = PHY_IS_INTERNAL,                              \
 897        .soft_reset     = genphy_soft_reset,                            \
 898        .config_init    = bcm7xxx_config_init,                          \
 899        .suspend        = bcm7xxx_suspend,                              \
 900        .resume         = bcm7xxx_config_init,                          \
 901}
 902
 903#define BCM7XXX_16NM_EPHY(_oui, _name)                                  \
 904{                                                                       \
 905        .phy_id         = (_oui),                                       \
 906        .phy_id_mask    = 0xfffffff0,                                   \
 907        .name           = _name,                                        \
 908        /* PHY_BASIC_FEATURES */                                        \
 909        .flags          = PHY_IS_INTERNAL,                              \
 910        .probe          = bcm7xxx_28nm_probe,                           \
 911        .remove         = bcm7xxx_28nm_remove,                          \
 912        .config_init    = bcm7xxx_16nm_ephy_config_init,                \
 913        .config_aneg    = genphy_config_aneg,                           \
 914        .read_status    = genphy_read_status,                           \
 915        .resume         = bcm7xxx_16nm_ephy_resume,                     \
 916}
 917
 918static struct phy_driver bcm7xxx_driver[] = {
 919        BCM7XXX_28NM_EPHY(PHY_ID_BCM72113, "Broadcom BCM72113"),
 920        BCM7XXX_28NM_EPHY(PHY_ID_BCM72116, "Broadcom BCM72116"),
 921        BCM7XXX_16NM_EPHY(PHY_ID_BCM72165, "Broadcom BCM72165"),
 922        BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
 923        BCM7XXX_28NM_EPHY(PHY_ID_BCM7255, "Broadcom BCM7255"),
 924        BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"),
 925        BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"),
 926        BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"),
 927        BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
 928        BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
 929        BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
 930        BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"),
 931        BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
 932        BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"),
 933        BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"),
 934        BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"),
 935        BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"),
 936        BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"),
 937        BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"),
 938        BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"),
 939        BCM7XXX_16NM_EPHY(PHY_ID_BCM7712, "Broadcom BCM7712"),
 940};
 941
 942static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
 943        { PHY_ID_BCM72113, 0xfffffff0 },
 944        { PHY_ID_BCM72116, 0xfffffff0, },
 945        { PHY_ID_BCM72165, 0xfffffff0, },
 946        { PHY_ID_BCM7250, 0xfffffff0, },
 947        { PHY_ID_BCM7255, 0xfffffff0, },
 948        { PHY_ID_BCM7260, 0xfffffff0, },
 949        { PHY_ID_BCM7268, 0xfffffff0, },
 950        { PHY_ID_BCM7271, 0xfffffff0, },
 951        { PHY_ID_BCM7278, 0xfffffff0, },
 952        { PHY_ID_BCM7364, 0xfffffff0, },
 953        { PHY_ID_BCM7366, 0xfffffff0, },
 954        { PHY_ID_BCM7346, 0xfffffff0, },
 955        { PHY_ID_BCM7362, 0xfffffff0, },
 956        { PHY_ID_BCM7425, 0xfffffff0, },
 957        { PHY_ID_BCM7429, 0xfffffff0, },
 958        { PHY_ID_BCM74371, 0xfffffff0, },
 959        { PHY_ID_BCM7439, 0xfffffff0, },
 960        { PHY_ID_BCM7435, 0xfffffff0, },
 961        { PHY_ID_BCM7445, 0xfffffff0, },
 962        { PHY_ID_BCM7712, 0xfffffff0, },
 963        { }
 964};
 965
 966module_phy_driver(bcm7xxx_driver);
 967
 968MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl);
 969
 970MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver");
 971MODULE_LICENSE("GPL");
 972MODULE_AUTHOR("Broadcom Corporation");
 973