/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask *butdoesn'tsupportchoosingbetweenXTAL/PLLandDSP.
*/ #define AT8035_CLK_OUT_MASK GENMASK(4, 3)
err = genphy_read_abilities(phydev); if (err) return err;
if (phydev->drv->phy_id != ATH8031_PHY_ID) return0;
/* AR8031/AR8033 have different status registers *forcopperandfiberoperation.However,the *extendedstatusregisteristhesameforboth *operationmodes. * *Asaresultofthat,ESTATUS_1000_XFULLisset *to1evenwhenoperatingincopperTPmode. * *Removethismodefromthesupportedlinkmodes *whennotoperatingin1000BaseXmode.
*/ if (!priv->is_1000basex)
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->supported);
return0;
}
staticint at803x_smarteee_config(struct phy_device *phydev)
{ struct at803x_priv *priv = phydev->priv;
u16 mask = 0, val = 0; int ret;
if (priv->flags & AT803X_DISABLE_SMARTEEE) return phy_modify_mmd(phydev, MDIO_MMD_PCS,
AT803X_MMD3_SMARTEEE_CTL3,
AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0);
if (priv->smarteee_lpi_tw_1g) {
mask |= 0xff00;
val |= priv->smarteee_lpi_tw_1g << 8;
} if (priv->smarteee_lpi_tw_100m) {
mask |= 0x00ff;
val |= priv->smarteee_lpi_tw_100m;
} if (!mask) return0;
ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL1,
mask, val); if (ret) return ret;
/* The default after hardware reset is PLL OFF. After a soft reset, the *valuesareretained.
*/ if (priv->flags & AT803X_KEEP_PLL_ENABLED) return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, 0, AT803X_DEBUG_PLL_ON); else return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
AT803X_DEBUG_PLL_ON, 0);
}
/* The default after hardware reset is hibernation mode enabled. After *softwarereset,thevalueisretained.
*/ if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE) &&
!(phydev->dev_flags & PHY_F_RXC_ALWAYS_ON)) return0;
staticint at803x_config_init(struct phy_device *phydev)
{ int ret;
/* The RX and TX delay default is: *afterHWreset:RXdelayenabledandTXdelaydisabled *afterSWreset:RXdelayenabled,whileTXdelayretainsthe *valuebeforereset.
*/ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
ret = at803x_enable_rx_delay(phydev); else
ret = at803x_disable_rx_delay(phydev); if (ret < 0) return ret;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
ret = at803x_enable_tx_delay(phydev); else
ret = at803x_disable_tx_delay(phydev); if (ret < 0) return ret;
ret = at803x_smarteee_config(phydev); if (ret < 0) return ret;
ret = at803x_clk_out_config(phydev); if (ret < 0) return ret;
ret = at803x_hibernation_mode_config(phydev); if (ret < 0) return ret;
/* Ar803x extended next page bit is enabled by default. Cisco *multigigswitchesreadthisbitandattempttonegotiate10Gbps *ratesevenifthenextpagebitisdisabled.Thisisincorrect *behaviourbutwestillneedtoaccommodateit.XNPisonlyneeded *for10Gbpssupport,sodisableXNP.
*/ return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0);
}
if (at803x_cdt_fault_length_valid(val)) {
val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val);
ethnl_cable_test_fault_length(phydev, ethtool_pair[pair],
at803x_cdt_fault_length(val));
}
return1;
}
staticint at803x_cable_test_get_status(struct phy_device *phydev, bool *finished, unsignedlong pair_mask)
{ int retries = 20; int pair, ret;
*finished = false;
/* According to the datasheet the CDT can be performed when *thereisnolinkpartnerorwhenthelinkpartneris *auto-negotiating.StartingthetestwillrestarttheAN *automatically.Itseemsthatdoingthisrepeatedlywewill *getaslotwhereourlinkpartnerwon'tdisturbour *measurement.
*/ while (pair_mask && retries--) {
for_each_set_bit(pair, &pair_mask, 4) {
ret = at803x_cable_test_one_pair(phydev, pair); if (ret < 0) return ret; if (ret)
clear_bit(pair, &pair_mask);
} if (pair_mask)
msleep(250);
}
*finished = true;
return0;
}
staticvoid at803x_cable_test_autoneg(struct phy_device *phydev)
{ /* Enable auto-negotiation, but advertise no capabilities, no link *willbeestablished.Arestartoftheauto-negotiationisnot *required,becausethecabletestwillautomaticallybreakthelink.
*/
phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA);
}
staticint at803x_cable_test_start(struct phy_device *phydev)
{
at803x_cable_test_autoneg(phydev); /* we do all the (time consuming) work later */ return0;
}
linkmode_zero(sfp_support);
sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); /* Some modules support 10G modes as well as others we support. *Maskoutnon-supportedmodessothecorrectinterfaceispicked.
*/
linkmode_and(sfp_support, phy_support, sfp_support);
/* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes *interfaceforusewithSFPmodules. *However,somecoppermodulesdetectedashavingapreferredSGMII *interfacedodefaulttoandfunctionin1000Base-Xmode,sojust *printawarningandallowsuchmodules,astheymayhavesomechance *ofworking.
*/ if (iface == PHY_INTERFACE_MODE_SGMII)
dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); elseif (iface != PHY_INTERFACE_MODE_1000BASEX) return -EINVAL;
switch (mode_cfg) { case AT803X_MODE_CFG_BX1000_RGMII_50OHM: case AT803X_MODE_CFG_BX1000_RGMII_75OHM:
priv->is_1000basex = true;
fallthrough; case AT803X_MODE_CFG_FX100_RGMII_50OHM: case AT803X_MODE_CFG_FX100_RGMII_75OHM:
priv->is_fiber = true; break;
}
/* Disable WoL in 1588 register which is enabled *bydefault
*/ return phy_modify_mmd(phydev, MDIO_MMD_PCS,
AT803X_PHY_MMD3_WOL_CTRL,
AT803X_WOL_EN, 0);
}
/* Some bootloaders leave the fiber page selected. *Switchtotheappropriatepage(fiberorcopper),asotherwisewe *readthePHYcapabilitiesfromthewrongpage.
*/
phy_lock_mdio_bus(phydev);
ret = at803x_write_page(phydev,
priv->is_fiber ? AT803X_PAGE_FIBER :
AT803X_PAGE_COPPER);
phy_unlock_mdio_bus(phydev); if (ret) return ret;
ret = at8031_pll_config(phydev); if (ret < 0) return ret;
return at803x_config_init(phydev);
}
staticint at8031_config_intr(struct phy_device *phydev)
{ struct at803x_priv *priv = phydev->priv; int err, value = 0;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED &&
priv->is_fiber) { /* Clear any pending interrupts */
err = at803x_ack_interrupt(phydev); if (err) return err;
value |= AT803X_INTR_ENABLE_LINK_FAIL_BX;
value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX;
err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); if (err) return err;
}
return at803x_config_intr(phydev);
}
/* AR8031 and AR8033 share the same read status logic */ staticint at8031_read_status(struct phy_device *phydev)
{ struct at803x_priv *priv = phydev->priv; bool changed;
if (priv->is_1000basex) return genphy_c37_read_status(phydev, &changed);
return at803x_read_status(phydev);
}
/* AR8031 and AR8035 share the same cable test get status reg */ staticint at8031_cable_test_get_status(struct phy_device *phydev, bool *finished)
{ return at803x_cable_test_get_status(phydev, finished, 0xf);
}
/* AR8031 and AR8035 share the same cable test start logic */ staticint at8031_cable_test_start(struct phy_device *phydev)
{
at803x_cable_test_autoneg(phydev);
phy_write(phydev, MII_CTRL1000, 0); /* we do all the (time consuming) work later */ return0;
}
/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ staticint at8032_cable_test_get_status(struct phy_device *phydev, bool *finished)
{ return at803x_cable_test_get_status(phydev, finished, 0x3);
}
/* Mask is set by the generic at803x_parse_dt *ifpropertyisset.Assumepropertyisset *withthemasknotzero.
*/ if (priv->clk_25m_mask) { /* Fixup for the AR8030/AR8035. This chip has another mask and *doesn'tsupporttheDSPreference.Eg.thelowestbitofthe *mask.Theuppertwobitsselectthesamefrequencies.Mask *thelowestbithere. * *Warning: *TherewasnodatasheetfortheAR8030availablesothisis *justaguess.ButtheAR8035islistedaspincompatible *totheAR8030sotheremightbeagoodchanceitworkson *theAR8030too.
*/
priv->clk_25m_reg &= AT8035_CLK_OUT_MASK;
priv->clk_25m_mask &= AT8035_CLK_OUT_MASK;
}
return0;
}
/* AR8030 and AR8035 shared the same special mask for clk_25m */ staticint at8035_probe(struct phy_device *phydev)
{ int ret;
/* PHY DAC values are optional and only set in a PHY to PHY link architecture */ if (priv->set_short_cable_dac) { /* setting MDAC (Multi-level Digital-to-Analog Converter) in MMD1 */
phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
IPQ5018_PHY_DAC_MASK, IPQ5018_PHY_MMD1_MDAC_VAL);
/* setting EDAC (Error-detection and Correction) in debug register */
at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
IPQ5018_PHY_DAC_MASK, IPQ5018_PHY_DEBUG_EDAC_VAL);
}
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.