cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bcm7xxx.c (27053B)


      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");