/** *genphy_c45_pma_baset1_setup_master_slave-configuresforcedmaster/slave *roleofBaseT1devices. *@phydev:targetphy_devicestruct
*/ int genphy_c45_pma_baset1_setup_master_slave(struct phy_device *phydev)
{ int ctl = 0;
switch (phydev->master_slave_set) { case MASTER_SLAVE_CFG_MASTER_PREFERRED: case MASTER_SLAVE_CFG_MASTER_FORCE:
ctl = MDIO_PMA_PMD_BT1_CTRL_CFG_MST; break; case MASTER_SLAVE_CFG_SLAVE_FORCE: case MASTER_SLAVE_CFG_SLAVE_PREFERRED: break; case MASTER_SLAVE_CFG_UNKNOWN: case MASTER_SLAVE_CFG_UNSUPPORTED: return0; default:
phydev_warn(phydev, "Unsupported Master/Slave mode\n"); return -EOPNOTSUPP;
}
switch (phydev->master_slave_set) { case MASTER_SLAVE_CFG_MASTER_FORCE:
adv_m |= MDIO_AN_T1_ADV_M_MST;
fallthrough; case MASTER_SLAVE_CFG_SLAVE_FORCE:
adv_l |= MDIO_AN_T1_ADV_L_FORCE_MS; break; case MASTER_SLAVE_CFG_MASTER_PREFERRED:
adv_m |= MDIO_AN_T1_ADV_M_MST;
fallthrough; case MASTER_SLAVE_CFG_SLAVE_PREFERRED: break; case MASTER_SLAVE_CFG_UNKNOWN: case MASTER_SLAVE_CFG_UNSUPPORTED: /* if master/slave role is not specified, do not overwrite it */
adv_l_mask &= ~MDIO_AN_T1_ADV_L_FORCE_MS;
adv_m_mask &= ~MDIO_AN_T1_ADV_M_MST; break; default:
phydev_warn(phydev, "Unsupported Master/Slave mode\n"); return -EOPNOTSUPP;
}
/* The link state is latched low so that momentary link *dropscanbedetected.Donotdouble-readthestatus *inpollingmodetodetectsuchshortlinkdropsexcept *thelinkwasalreadydown.
*/ if (!phy_polling_mode(phydev) || !phydev->link) {
val = phy_read_mmd(phydev, devad, MDIO_STAT1); if (val < 0) return val; elseif (val & MDIO_STAT1_LSTATUS) continue;
}
val = phy_read_mmd(phydev, devad, MDIO_STAT1); if (val < 0) return val;
/* Read the Clause 45 defined BASE-T1 AN (7.513) status register to check *ifautonegiscomplete.IfsoreadtheBASE-T1Autonegotiation *Advertisementregistersfillinginthelinkpartneradvertisement, *pauseandasym_pausemembersinphydev.
*/ staticint genphy_c45_baset1_read_lpa(struct phy_device *phydev)
{ int val;
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_STAT); if (val < 0) return val;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
phydev->supported_eee)) {
val = linkmode_adv_to_mii_10base_t1_t(adv); /* IEEE 802.3cg-2019 45.2.7.25 10BASE-T1 AN control register *(Register7.526)
*/
val = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,
MDIO_AN_10BT1_AN_CTRL,
MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L,
val); if (val < 0) return val; if (val > 0)
changed = 1;
}
return changed;
}
/** *genphy_c45_read_eee_adv-readadvertisedEEElinkmodes *@phydev:targetphy_devicestruct *@adv:thelinkmodeadvertisementstatus
*/ int genphy_c45_read_eee_adv(struct phy_device *phydev, unsignedlong *adv)
{ int val;
if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP1_FEATURES)) { /* IEEE 802.3-2018 45.2.7.13 EEE advertisement 1 *(Register7.60)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV); if (val < 0) return val;
mii_eee_cap1_mod_linkmode_t(adv, val);
}
if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP2_FEATURES)) { /* IEEE 802.3-2022 45.2.7.16 EEE advertisement 2 *(Register7.62)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV2); if (val < 0) return val;
mii_eee_cap2_mod_linkmode_adv_t(adv, val);
}
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
phydev->supported_eee)) { /* IEEE 802.3cg-2019 45.2.7.25 10BASE-T1 AN control register *(Register7.526)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10BT1_AN_CTRL); if (val < 0) return val;
if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP1_FEATURES)) { /* IEEE 802.3-2018 45.2.7.14 EEE link partner ability 1 *(Register7.61)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); if (val < 0) return val;
mii_eee_cap1_mod_linkmode_t(lpa, val);
}
if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP2_FEATURES)) { /* IEEE 802.3-2022 45.2.7.17 EEE link partner ability 2 *(Register7.63)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE2); if (val < 0) return val;
mii_eee_cap2_mod_linkmode_adv_t(lpa, val);
}
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
phydev->supported_eee)) { /* IEEE 802.3cg-2019 45.2.7.26 10BASE-T1 AN status register *(Register7.527)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10BT1_AN_STAT); if (val < 0) return val;
/* IEEE 802.3-2018 45.2.3.10 EEE control and capability 1 *(Register3.20)
*/
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); if (val < 0) return val;
/* The 802.3 2018 standard says the top 2 bits are reserved and should *readas0.Also,itseemsunlikelyanybodywillbuildaPHYwhich *supports100GBASE-Rdeepsleepallthewaydownto100BASE-TXEEE. *IfMDIO_PCS_EEE_ABLEis0xffffassumeEEEisnotsupported.
*/ if (val == 0xffff) return0;
/* Some buggy devices indicate EEE link modes in MDIO_PCS_EEE_ABLE *whichtheydon'tsupportasindicatedbyBMSR,ESTATUSetc.
*/
linkmode_and(phydev->supported_eee, phydev->supported_eee,
phydev->supported);
/** *genphy_c45_read_eee_abilities-readsupportedEEElinkmodes *@phydev:targetphy_devicestruct
*/ int genphy_c45_read_eee_abilities(struct phy_device *phydev)
{ int val;
/* There is not indicator whether optional register *"EEEcontrolandcapability1"(3.20)issupported.Readitonly *ondeviceswithappropriatelinkmodes.
*/ if (linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)) {
val = genphy_c45_read_eee_cap1(phydev); if (val) return val;
}
/* Same for cap2 (3.21) */ if (linkmode_intersects(phydev->supported, PHY_EEE_CAP2_FEATURES)) {
val = genphy_c45_read_eee_cap2(phydev); if (val) return val;
}
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
phydev->supported)) { /* IEEE 802.3cg-2019 45.2.1.186b 10BASE-T1L PMA status register *(Register1.2295)
*/
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
phydev->supported_eee,
val & MDIO_PMA_10T1L_STAT_EEE);
}
/** *genphy_c45_pma_read_ext_abilities-readsupportedlinkmodesfromPMA *@phydev:targetphy_devicestruct * *ReadthesupportedlinkmodesfromthePMA/PMDextendedabilityregister *(Register1.11).
*/ int genphy_c45_pma_read_ext_abilities(struct phy_device *phydev)
{ int val;
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBLRM);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBKX4);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10GBKR);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_1000BT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_1000BKX);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_100BTX);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_100BTX);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10BT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
phydev->supported,
val & MDIO_PMA_EXTABLE_10BT);
if (val & MDIO_PMA_EXTABLE_NBT) {
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
MDIO_PMA_NG_EXTABLE); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_NG_EXTABLE_2_5GBT);
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->supported,
val & MDIO_PMA_NG_EXTABLE_5GBT);
}
if (val & MDIO_PMA_EXTABLE_BT1) {
val = genphy_c45_pma_baset1_read_abilities(phydev); if (val < 0) return val;
}
/* Read master/slave preference from registers. *ThepreferenceisreadfromtheBIT(4)ofBASE-T1AN *advertisementregister7.515andwhetherthepreference *isforcedornot,itisreadfromBASE-T1ANadvertisement *register7.514.
*/ int genphy_c45_baset1_read_status(struct phy_device *phydev)
{ int ret; int cfg;
/** *genphy_c45_fast_retrain-configurefastretrainregisters *@phydev:targetphy_devicestruct *@enable:enablefastretrainornot * *Description:Iffast-retrainisenabled,weconfigurePHYas *advertisingfastretraincapableandTHPBypassRequest,then *enablefastretrain.Ifitisnotenabled,weconfigurefast *retraindisabled.
*/ int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)
{ int ret;
if (!enable) return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FSRT_CSR,
MDIO_PMA_10GBR_FSRT_ENABLE);
if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported)) {
ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
MDIO_AN_10GBT_CTRL_ADVFSRT2_5G); if (ret) return ret;
ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_CTRL2,
MDIO_AN_THP_BP2_5GT); if (ret) return ret;
}
/** *genphy_c45_plca_set_cfg-setPLCAconfigurationusingstandardregisters *@phydev:targetphy_devicestruct *@plca_cfg:structurecontainingthePLCAconfiguration.Fieldssetto-1are *nottobechanged. * *Description:ifthePHYcompliestotheOpenAllianceTC1410BASE-T1SPLCA *ManagementRegistersspecifications,thisfunctioncanbeusedtomodify *thePLCAconfigurationusingthestandardregistersinMMD31.
*/ int genphy_c45_plca_set_cfg(struct phy_device *phydev, conststruct phy_plca_cfg *plca_cfg)
{
u16 val = 0; int ret;
// PLCA IDVER is read-only if (plca_cfg->version >= 0) return -EINVAL;
// first of all, disable PLCA if required if (plca_cfg->enabled == 0) {
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_CTRL0,
MDIO_OATC14_PLCA_EN);
if (ret < 0) return ret;
}
// check if we need to set the PLCA node count, node ID, or both if (plca_cfg->node_cnt >= 0 || plca_cfg->node_id >= 0) { /* if one between node count and node ID is -not- to be *changed,readtheregistertolaterperformmerge/purgeof *theconfigurationasappropriate
*/ if (plca_cfg->node_cnt < 0 || plca_cfg->node_id < 0) {
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_CTRL1);
if (ret < 0) return ret;
val = ret;
}
if (plca_cfg->node_cnt >= 0)
val = (val & ~MDIO_OATC14_PLCA_NCNT) |
(plca_cfg->node_cnt << 8);
if (plca_cfg->node_id >= 0)
val = (val & ~MDIO_OATC14_PLCA_ID) |
(plca_cfg->node_id);
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_CTRL1, val);
if (ret < 0) return ret;
}
if (plca_cfg->to_tmr >= 0) {
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_TOTMR,
plca_cfg->to_tmr);
if (ret < 0) return ret;
}
// check if we need to set the PLCA burst count, burst timer, or both if (plca_cfg->burst_cnt >= 0 || plca_cfg->burst_tmr >= 0) { /* if one between burst count and burst timer is -not- to be *changed,readtheregistertolaterperformmerge/purgeof *theconfigurationasappropriate
*/ if (plca_cfg->burst_cnt < 0 || plca_cfg->burst_tmr < 0) {
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_BURST);
if (ret < 0) return ret;
val = ret;
}
if (plca_cfg->burst_cnt >= 0)
val = (val & ~MDIO_OATC14_PLCA_MAXBC) |
(plca_cfg->burst_cnt << 8);
if (plca_cfg->burst_tmr >= 0)
val = (val & ~MDIO_OATC14_PLCA_BTMR) |
(plca_cfg->burst_tmr);
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_BURST, val);
if (ret < 0) return ret;
}
// if we need to enable PLCA, do it at the end if (plca_cfg->enabled > 0) {
ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
MDIO_OATC14_PLCA_CTRL0,
MDIO_OATC14_PLCA_EN);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.