/** * genphy_c45_pma_can_sleep - checks if the PMA have sleep support * @phydev: target phy_device struct
*/ staticbool genphy_c45_pma_can_sleep(struct phy_device *phydev)
{ int stat1;
stat1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT1); if (stat1 < 0) returnfalse;
return !!(stat1 & MDIO_STAT1_LPOWERABLE);
}
/** * genphy_c45_pma_resume - wakes up the PMA module * @phydev: target phy_device struct
*/ int genphy_c45_pma_resume(struct phy_device *phydev)
{ if (!genphy_c45_pma_can_sleep(phydev)) return -EOPNOTSUPP;
/** * genphy_c45_pma_baset1_setup_master_slave - configures forced master/slave * role of BaseT1 devices. * @phydev: target phy_device struct
*/ 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: return 0; default:
phydev_warn(phydev, "Unsupported Master/Slave mode\n"); return -EOPNOTSUPP;
}
ctrl1 &= ~MDIO_CTRL1_SPEEDSEL; /* * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0. See 45.2.1.6.1 * in 802.3-2012 and 802.3-2015.
*/
ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
/* Sets master/slave preference and supported technologies. * The preference is set in the BIT(4) of BASE-T1 AN * advertisement register 7.515 and whether the status * is forced or not, it is set in the BIT(12) of BASE-T1 * AN advertisement register 7.514. * Sets 10BASE-T1L Ability BIT(14) in BASE-T1 autonegotiation * advertisement register [31:16] if supported.
*/ staticint genphy_c45_baset1_an_config_aneg(struct phy_device *phydev)
{
u16 adv_l_mask, adv_l = 0;
u16 adv_m_mask, adv_m = 0; int changed = 0; int ret;
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;
}
/** * genphy_c45_an_disable_aneg - disable auto-negotiation * @phydev: target phy_device struct * * Disable auto-negotiation in the Clause 45 PHY. The link parameters * are controlled through the PMA/PMD MMD registers. * * Returns zero on success, negative errno code on failure.
*/ int genphy_c45_an_disable_aneg(struct phy_device *phydev)
{
u16 reg = MDIO_CTRL1;
if (genphy_c45_baset1_able(phydev))
reg = MDIO_AN_T1_CTRL;
/** * genphy_c45_aneg_done - return auto-negotiation complete status * @phydev: target phy_device struct * * This assumes that the auto-negotiation MMD is present. * * Reads the status register from the auto-negotiation MMD, returning: * - positive if auto-negotiation is complete * - negative errno code on error * - zero otherwise
*/ int genphy_c45_aneg_done(struct phy_device *phydev)
{ int reg = MDIO_STAT1; int val;
if (genphy_c45_baset1_able(phydev))
reg = MDIO_AN_T1_STAT;
val = phy_read_mmd(phydev, MDIO_MMD_AN, reg);
return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
}
EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
/** * genphy_c45_read_link - read the overall link status from the MMDs * @phydev: target phy_device struct * * Read the link status from the specified MMDs, and if they all indicate * that the link is up, set phydev->link to 1. If an error is encountered, * a negative errno will be returned, otherwise zero.
*/ int genphy_c45_read_link(struct phy_device *phydev)
{
u32 mmd_mask = MDIO_DEVS_PMAPMD; int val, devad; bool link = true;
if (phydev->c45_ids.mmds_present & MDIO_DEVS_AN) {
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); if (val < 0) return val;
/* Autoneg is being started, therefore disregard current * link status and report link as down.
*/ if (val & MDIO_AN_CTRL1_RESTART) {
phydev->link = 0; return 0;
}
}
/* The link state is latched low so that momentary link * drops can be detected. Do not double-read the status * in polling mode to detect such short link drops except * the link was already down.
*/ 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 * if autoneg is complete. If so read the BASE-T1 Autonegotiation * Advertisement registers filling in the link partner advertisement, * pause and asym_pause members in phydev.
*/ 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;
/** * genphy_c45_read_lpa - read the link partner advertisement and pause * @phydev: target phy_device struct * * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers, * filling in the link partner advertisement, pause and asym_pause members * in @phydev. This assumes that the auto-negotiation MMD is present, and * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected * to fill in the remainder of the link partner advert from vendor registers.
*/ int genphy_c45_read_lpa(struct phy_device *phydev)
{ int val;
if (genphy_c45_baset1_able(phydev)) return genphy_c45_baset1_read_lpa(phydev);
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); 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 * (Register 7.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 - read advertised EEE link modes * @phydev: target phy_device struct * @adv: the linkmode advertisement status
*/ 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 * (Register 7.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 * (Register 7.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 * (Register 7.526)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10BT1_AN_CTRL); if (val < 0) return val;
mii_10base_t1_adv_mod_linkmode_t(adv, val);
}
return 0;
}
/** * genphy_c45_read_eee_lpa - read advertised LP EEE link modes * @phydev: target phy_device struct * @lpa: the linkmode LP advertisement status
*/ staticint genphy_c45_read_eee_lpa(struct phy_device *phydev, unsignedlong *lpa)
{ int val;
if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP1_FEATURES)) { /* IEEE 802.3-2018 45.2.7.14 EEE link partner ability 1 * (Register 7.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 * (Register 7.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 * (Register 7.527)
*/
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10BT1_AN_STAT); if (val < 0) return val;
mii_10base_t1_adv_mod_linkmode_t(lpa, val);
}
return 0;
}
/** * genphy_c45_read_eee_cap1 - read supported EEE link modes from register 3.20 * @phydev: target phy_device struct
*/ staticint genphy_c45_read_eee_cap1(struct phy_device *phydev)
{ int val;
/* IEEE 802.3-2018 45.2.3.10 EEE control and capability 1 * (Register 3.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 * read as 0. Also, it seems unlikely anybody will build a PHY which * supports 100GBASE-R deep sleep all the way down to 100BASE-TX EEE. * If MDIO_PCS_EEE_ABLE is 0xffff assume EEE is not supported.
*/ if (val == 0xffff) return 0;
/* Some buggy devices indicate EEE link modes in MDIO_PCS_EEE_ABLE * which they don't support as indicated by BMSR, ESTATUS etc.
*/
linkmode_and(phydev->supported_eee, phydev->supported_eee,
phydev->supported);
return 0;
}
/** * genphy_c45_read_eee_cap2 - read supported EEE link modes from register 3.21 * @phydev: target phy_device struct
*/ staticint genphy_c45_read_eee_cap2(struct phy_device *phydev)
{ int val;
/* IEEE 802.3-2022 45.2.3.11 EEE control and capability 2 * (Register 3.21)
*/
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE2); if (val < 0) return val;
/* IEEE 802.3-2022 45.2.3.11 says 9 bits are reserved. */ if (val == 0xffff) return 0;
/** * genphy_c45_read_eee_abilities - read supported EEE link modes * @phydev: target phy_device struct
*/ int genphy_c45_read_eee_abilities(struct phy_device *phydev)
{ int val;
/* There is not indicator whether optional register * "EEE control and capability 1" (3.20) is supported. Read it only * on devices with appropriate linkmodes.
*/ 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 * (Register 1.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_baset1_read_abilities - read supported baset1 link modes from PMA * @phydev: target phy_device struct * * Read the supported link modes from the extended BASE-T1 ability register
*/ int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev)
{ int val;
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_PMD_BT1); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
phydev->supported,
val & MDIO_PMA_PMD_BT1_B10L_ABLE);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
phydev->supported,
val & MDIO_PMA_PMD_BT1_B100_ABLE);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT,
phydev->supported,
val & MDIO_PMA_PMD_BT1_B1000_ABLE);
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_STAT); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
phydev->supported,
val & MDIO_AN_STAT1_ABLE);
/** * genphy_c45_pma_read_ext_abilities - read supported link modes from PMA * @phydev: target phy_device struct * * Read the supported link modes from the PMA/PMD extended ability register * (Register 1.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;
}
/** * genphy_c45_pma_read_abilities - read supported link modes from PMA * @phydev: target phy_device struct * * Read the supported link modes from the PMA Status 2 (1.8) register. If bit * 1.8.9 is set, the list of supported modes is build using the values in the * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related * modes. If bit 1.11.14 is set, then the list is also extended with the modes * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and * 5GBASET are supported.
*/ int genphy_c45_pma_read_abilities(struct phy_device *phydev)
{ int val;
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); if (phydev->c45_ids.mmds_present & MDIO_DEVS_AN) {
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); if (val < 0) return val;
if (val & MDIO_AN_STAT1_ABLE)
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
phydev->supported);
}
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
phydev->supported,
val & MDIO_PMA_STAT2_10GBSR);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
phydev->supported,
val & MDIO_PMA_STAT2_10GBLR);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
phydev->supported,
val & MDIO_PMA_STAT2_10GBER);
if (val & MDIO_PMA_STAT2_EXTABLE) {
val = genphy_c45_pma_read_ext_abilities(phydev); if (val < 0) return val;
}
/* This is optional functionality. If not supported, we may get an error * which should be ignored.
*/
genphy_c45_read_eee_abilities(phydev);
/* Read master/slave preference from registers. * The preference is read from the BIT(4) of BASE-T1 AN * advertisement register 7.515 and whether the preference * is forced or not, it is read from BASE-T1 AN advertisement * register 7.514.
*/ int genphy_c45_baset1_read_status(struct phy_device *phydev)
{ int ret; int cfg;
/** * genphy_c45_read_status - read PHY status * @phydev: target phy_device struct * * Reads status from PHY and sets phy_device members accordingly.
*/ int genphy_c45_read_status(struct phy_device *phydev)
{ int ret;
ret = genphy_c45_read_link(phydev); if (ret) return ret;
/** * genphy_c45_config_aneg - restart auto-negotiation or forced setup * @phydev: target phy_device struct * * Description: If auto-negotiation is enabled, we configure the * advertising, and then restart auto-negotiation. If it is not * enabled, then we force a configuration.
*/ int genphy_c45_config_aneg(struct phy_device *phydev)
{ bool changed = false; int ret;
if (phydev->autoneg == AUTONEG_DISABLE) return genphy_c45_pma_setup_forced(phydev);
ret = genphy_c45_an_config_aneg(phydev); if (ret < 0) return ret; if (ret > 0)
changed = true;
/** * genphy_c45_fast_retrain - configure fast retrain registers * @phydev: target phy_device struct * @enable: enable fast retrain or not * * Description: If fast-retrain is enabled, we configure PHY as * advertising fast retrain capable and THP Bypass Request, then * enable fast retrain. If it is not enabled, we configure fast * retrain disabled.
*/ 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_get_cfg - get PLCA configuration from standard registers * @phydev: target phy_device struct * @plca_cfg: output structure to store the PLCA configuration * * Description: if the PHY complies to the Open Alliance TC14 10BASE-T1S PLCA * Management Registers specifications, this function can be used to retrieve * the current PLCA configuration from the standard registers in MMD 31.
*/ int genphy_c45_plca_get_cfg(struct phy_device *phydev, struct phy_plca_cfg *plca_cfg)
{ int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_IDVER); if (ret < 0) return ret;
if ((ret & MDIO_OATC14_PLCA_IDM) != OATC14_IDM) return -ENODEV;
plca_cfg->version = ret & ~MDIO_OATC14_PLCA_IDM;
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_CTRL0); if (ret < 0) return ret;
/** * genphy_c45_plca_set_cfg - set PLCA configuration using standard registers * @phydev: target phy_device struct * @plca_cfg: structure containing the PLCA configuration. Fields set to -1 are * not to be changed. * * Description: if the PHY complies to the Open Alliance TC14 10BASE-T1S PLCA * Management Registers specifications, this function can be used to modify * the PLCA configuration using the standard registers in MMD 31.
*/ 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, read the register to later perform merge/purge of * the configuration as appropriate
*/ 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, read the register to later perform merge/purge of * the configuration as appropriate
*/ 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);
/** * genphy_c45_plca_get_status - get PLCA status from standard registers * @phydev: target phy_device struct * @plca_st: output structure to store the PLCA status * * Description: if the PHY complies to the Open Alliance TC14 10BASE-T1S PLCA * Management Registers specifications, this function can be used to retrieve * the current PLCA status information from the standard registers in MMD 31.
*/ int genphy_c45_plca_get_status(struct phy_device *phydev, struct phy_plca_status *plca_st)
{ int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_STATUS); if (ret < 0) return ret;
/** * genphy_c45_eee_is_active - get EEE status * @phydev: target phy_device struct * @lp: variable to store LP advertised linkmodes * * Description: this function will read link partner PHY advertisement * and compare it to local advertisement to return current EEE state.
*/ int genphy_c45_eee_is_active(struct phy_device *phydev, unsignedlong *lp)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_lp) = {};
__ETHTOOL_DECLARE_LINK_MODE_MASK(common); int ret;
if (!phydev->eee_cfg.eee_enabled) return 0;
ret = genphy_c45_read_eee_lpa(phydev, tmp_lp); if (ret) return ret;
if (lp)
linkmode_copy(lp, tmp_lp);
linkmode_and(common, phydev->advertising_eee, tmp_lp); if (linkmode_empty(common)) return 0;
/** * genphy_c45_ethtool_get_eee - get EEE supported and status * @phydev: target phy_device struct * @data: ethtool_keee data * * Description: it reports the Supported/Advertisement/LP Advertisement * capabilities.
*/ int genphy_c45_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data)
{ int ret;
ret = genphy_c45_eee_is_active(phydev, data->lp_advertised); if (ret < 0) return ret;
/** * genphy_c45_ethtool_set_eee - set EEE supported and status * @phydev: target phy_device struct * @data: ethtool_keee data * * Description: sets the Supported/Advertisement/LP Advertisement * capabilities. If eee_enabled is false, no links modes are * advertised, but the previously advertised link modes are * retained. This allows EEE to be enabled/disabled in a * non-destructive way. * Returns either error code, 0 if there was no change, or positive * value if there was a change which triggered auto-neg.
*/ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data)
{ int ret;
if (data->eee_enabled) { unsignedlong *adv = data->advertised;
if (!linkmode_empty(adv)) {
__ETHTOOL_DECLARE_LINK_MODE_MASK(tmp);
if (linkmode_andnot(tmp, adv, phydev->supported_eee)) {
phydev_warn(phydev, "At least some EEE link modes are not supported.\n"); return -EINVAL;
}
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.