0001
0002
0003
0004
0005
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
0018
0019
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
0054 bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
0055
0056
0057 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
0058
0059
0060 bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
0061
0062
0063 bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
0064
0065
0066 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
0067
0068
0069 bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
0070
0071
0072 bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
0073
0074
0075
0076
0077 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
0078
0079
0080 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
0081
0082
0083 bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
0084
0085
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
0094 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
0095
0096
0097 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
0098
0099
0100 bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
0101
0102
0103
0104
0105 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
0106
0107
0108 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010);
0109
0110
0111 bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
0112
0113
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
0122 bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
0123
0124
0125 bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
0126
0127
0128 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
0129
0130
0131 bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
0132
0133
0134 bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
0135
0136
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
0152
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
0161
0162
0163
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
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
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
0212 ret = bcm7xxx_28nm_config_init(phydev);
0213 if (ret)
0214 return ret;
0215
0216
0217
0218
0219
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
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
0266 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0);
0267 if (ret < 0)
0268 goto reset_shadow_mode;
0269
0270
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
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
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
0301 static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev)
0302 {
0303 int ret;
0304
0305
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
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
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
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
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
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
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
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
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
0398
0399
0400
0401
0402 phy_read(phydev, MII_BMSR);
0403
0404
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
0423 tmp = genphy_soft_reset(phydev);
0424 if (tmp)
0425 return tmp;
0426
0427
0428 bcm_phy_write_exp_sel(phydev, 0x0003, 0x0006);
0429
0430 bcm_phy_write_exp_sel(phydev, 0x0003, 0x0000);
0431
0432
0433 bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0000);
0434 bcm_phy_write_misc(phydev, 0x0031, 0x0000, 0x044a);
0435
0436
0437 bcm_phy_write_misc(phydev, 0x0033, 0x0002, 0x71a1);
0438
0439 bcm_phy_write_misc(phydev, 0x0033, 0x0001, 0x8000);
0440
0441
0442 bcm_phy_write_misc(phydev, 0x0031, 0x0001, 0x2f68);
0443 bcm_phy_write_misc(phydev, 0x0031, 0x0002, 0x0000);
0444
0445
0446
0447
0448 bcm_phy_write_misc(phydev, 0x0030, 0x0003, 0xc036);
0449
0450
0451 bcm_phy_write_misc(phydev, 0x0032, 0x0003, 0x0000);
0452
0453 bcm_phy_write_misc(phydev, 0x0033, 0x0000, 0x0002);
0454
0455 bcm_phy_write_misc(phydev, 0x0030, 0x0002, 0x01c0);
0456
0457 bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0001);
0458
0459
0460 bcm_phy_write_misc(phydev, 0x0038, 0x0000, 0x0010);
0461
0462
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
0470 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x1c82);
0471
0472 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e82);
0473 udelay(2);
0474
0475 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f82);
0476 udelay(100);
0477
0478 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e86);
0479 udelay(2);
0480
0481 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f86);
0482 udelay(100);
0483
0484
0485 bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7ea);
0486
0487 bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0);
0488
0489
0490 tmp = bcm_phy_read_exp(phydev, 0x00a9);
0491
0492 rcalcode = (tmp & 0x7e) / 2;
0493
0494 rcalnewcodelp = rcalcode + 16;
0495
0496 rcalnewcode11 = rcalcode + 10;
0497
0498 if (rcalnewcodelp > 0x3f)
0499 rcalnewcodelp = 0x3f;
0500 if (rcalnewcode11 > 0x3f)
0501 rcalnewcode11 = 0x3f;
0502
0503 tmp = 0x00f8 + rcalnewcodelp * 256;
0504
0505 bcm_phy_write_misc(phydev, 0x0039, 0x0003, tmp);
0506
0507 bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7e4);
0508
0509
0510
0511 bcm_phy_write_misc(phydev, 0x003b, 0x0000, 0x8002);
0512
0513 bcm_phy_write_misc(phydev, 0x003c, 0x0003, 0xf882);
0514
0515
0516
0517 bcm_phy_write_misc(phydev, 0x003d, 0x0000, 0x3201);
0518
0519 bcm_phy_write_misc(phydev, 0x003a, 0x0002, 0x0c00);
0520
0521
0522
0523
0524 bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0020);
0525
0526
0527 bcm_phy_write_misc(phydev, 0x003b, 0x0002, 0x0000);
0528 bcm_phy_write_misc(phydev, 0x003b, 0x0003, 0x0000);
0529
0530
0531 bcm_phy_write_misc(phydev, 0x003a, 0x0003, 0x0800);
0532 udelay(2);
0533
0534
0535
0536
0537 bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0000);
0538
0539
0540 rcalnewcode11d2 = (rcalnewcode11 & 0xfffe) / 2;
0541 tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0001);
0542
0543 tmp &= ~0xfe0;
0544
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
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
0578
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
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
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
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
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
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
0676 ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
0677 if (ret < 0)
0678 goto reset_shadow_mode;
0679
0680
0681 __phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
0682
0683 reset_shadow_mode:
0684
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
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
0706 phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO);
0707 phy_read(phydev, MII_BCM7XXX_AUX_MODE);
0708
0709
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
0716 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00);
0717 udelay(10);
0718
0719
0720 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00);
0721
0722 phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
0723
0724
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
0733
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
0793
0794
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
0837
0838
0839
0840
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 \
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 \
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 \
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 \
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");