/* Sleep and timeout for checking if the Processor-Intensive * MDIO operation is finished
*/ #define AQR107_OP_IN_PROG_SLEEP 1000 #define AQR107_OP_IN_PROG_TIMEOUT 100000
for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) {
val = aqr107_get_stat(phydev, i); if (val == U64_MAX)
phydev_err(phydev, "Reading HW Statistics failed for %s\n",
aqr107_hw_stats[i].name); else
priv->sgmii_stats[i] += val;
data[i] = priv->sgmii_stats[i];
}
}
staticint aqr_set_mdix(struct phy_device *phydev, int mdix)
{
u16 val = 0;
switch (mdix) { case ETH_TP_MDI:
val = MDIO_AN_RESVD_VEND_PROV_MDIX_MDI; break; case ETH_TP_MDI_X:
val = MDIO_AN_RESVD_VEND_PROV_MDIX_MDIX; break; case ETH_TP_MDI_AUTO: case ETH_TP_MDI_INVALID: default:
val = MDIO_AN_RESVD_VEND_PROV_MDIX_AUTO; break;
}
ret = aqr_set_mdix(phydev, phydev->mdix_ctrl); if (ret < 0) return ret; if (ret > 0)
changed = true;
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;
/* Clause 45 has no standardized support for 1000BaseT, therefore * use vendor registers for this mode.
*/
reg = 0; if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_1000BASET_FULL;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_1000BASET_HALF;
/* Handle the case when the 2.5G and 5G speeds are not advertised */ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_2500BASET_FULL;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_5000BASET_FULL;
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV,
MDIO_AN_VEND_PROV_1000BASET_HALF |
MDIO_AN_VEND_PROV_1000BASET_FULL |
MDIO_AN_VEND_PROV_2500BASET_FULL |
MDIO_AN_VEND_PROV_5000BASET_FULL, reg); if (ret < 0) return ret; if (ret > 0)
changed = true;
staticint aqr_config_intr(struct phy_device *phydev)
{ bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; int err;
if (en) { /* Clear any pending interrupts before enabling them */
err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); if (err < 0) return err;
}
err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2,
en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); if (err < 0) return err;
err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK,
en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); if (err < 0) return err;
err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK,
en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 |
VEND1_GLOBAL_INT_VEND_MASK_AN : 0); if (err < 0) return err;
if (!en) { /* Clear any pending interrupts after we have disabled them */
err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); if (err < 0) return err;
}
return 0;
}
static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev)
{ int irq_status;
if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
staticint aqr_read_status(struct phy_device *phydev)
{ int val;
if (phydev->autoneg == AUTONEG_ENABLE) {
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->lp_advertising,
val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->lp_advertising,
val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF);
}
val = genphy_c45_aneg_done(phydev); if (val < 0) return val; if (val) {
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RESVD_VEND_STATUS1); if (val < 0) return val; if (val & MDIO_AN_RESVD_VEND_STATUS1_MDIX)
phydev->mdix = ETH_TP_MDI_X; else
phydev->mdix = ETH_TP_MDI;
} else {
phydev->mdix = ETH_TP_MDI_INVALID;
}
return genphy_c45_read_status(phydev);
}
staticint aqr105_get_features(struct phy_device *phydev)
{ int ret;
/* Normal feature discovery */
ret = genphy_c45_pma_read_abilities(phydev); if (ret) return ret;
/* The AQR105 PHY misses to indicate the 2.5G and 5G modes, so add them * here
*/
linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->supported);
/* The AQR105 PHY suppports both RJ45 and SFP+ interfaces */
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
return 0;
}
staticint aqr105_setup_forced(struct phy_device *phydev)
{ int vend = MDIO_AN_VEND_PROV_EXC_PHYID_INFO; int ctrl10 = 0; int adv = ADVERTISE_CSMA; int ret;
switch (phydev->speed) { case SPEED_100:
adv |= ADVERTISE_100FULL; break; case SPEED_1000:
adv |= ADVERTISE_NPAGE; if (phydev->duplex == DUPLEX_FULL)
vend |= MDIO_AN_VEND_PROV_1000BASET_FULL; else
vend |= MDIO_AN_VEND_PROV_1000BASET_HALF; break; case SPEED_2500:
adv |= (ADVERTISE_NPAGE | ADVERTISE_RESV);
vend |= MDIO_AN_VEND_PROV_2500BASET_FULL; break; case SPEED_5000:
adv |= (ADVERTISE_NPAGE | ADVERTISE_RESV);
vend |= MDIO_AN_VEND_PROV_5000BASET_FULL; break; case SPEED_10000:
adv |= (ADVERTISE_NPAGE | ADVERTISE_RESV);
ctrl10 |= MDIO_AN_10GBT_CTRL_ADV10G; break; default: return -EINVAL;
}
ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, adv); if (ret < 0) return ret;
ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, vend); if (ret < 0) return ret;
ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ctrl10); if (ret < 0) return ret;
/* set by vendor driver, but should be on by default */
ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
MDIO_AN_CTRL1_XNP); if (ret < 0) return ret;
ret = aqr_set_mdix(phydev, phydev->mdix_ctrl); if (ret < 0) return ret; if (ret > 0)
changed = true;
if (phydev->autoneg == AUTONEG_DISABLE) return aqr105_setup_forced(phydev);
ret = genphy_c45_an_config_aneg(phydev); if (ret < 0) return ret; if (ret > 0)
changed = true;
/* Clause 45 has no standardized support for 1000BaseT, therefore * use vendor registers for this mode.
*/
reg = 0; if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_1000BASET_FULL;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_1000BASET_HALF;
/* Handle the case when the 2.5G and 5G speeds are not advertised */ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_2500BASET_FULL;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->advertising))
reg |= MDIO_AN_VEND_PROV_5000BASET_FULL;
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV,
MDIO_AN_VEND_PROV_1000BASET_HALF |
MDIO_AN_VEND_PROV_1000BASET_FULL |
MDIO_AN_VEND_PROV_2500BASET_FULL |
MDIO_AN_VEND_PROV_5000BASET_FULL, reg); if (ret < 0) return ret; if (ret > 0)
changed = true;
switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { case MDIO_AN_TX_VEND_STATUS1_10BASET:
phydev->speed = SPEED_10; break; case MDIO_AN_TX_VEND_STATUS1_100BASETX:
phydev->speed = SPEED_100; break; case MDIO_AN_TX_VEND_STATUS1_1000BASET:
phydev->speed = SPEED_1000; break; case MDIO_AN_TX_VEND_STATUS1_2500BASET:
phydev->speed = SPEED_2500; break; case MDIO_AN_TX_VEND_STATUS1_5000BASET:
phydev->speed = SPEED_5000; break; case MDIO_AN_TX_VEND_STATUS1_10GBASET:
phydev->speed = SPEED_10000; break; default:
phydev->speed = SPEED_UNKNOWN;
}
return 0;
}
staticint aqr105_read_status(struct phy_device *phydev)
{ int ret; int val;
ret = aqr_read_status(phydev); if (ret) return ret;
if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) return 0;
/* The status register is not immediately correct on line side link up. * Poll periodically until it reflects the correct ON state. * Only return fail for read error, timeout defaults to OFF state.
*/
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PHYXS,
MDIO_PHYXS_VEND_IF_STATUS, val,
(FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val) !=
MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF),
AQR107_OP_IN_PROG_SLEEP,
AQR107_OP_IN_PROG_TIMEOUT, false); if (ret && ret != -ETIMEDOUT) return ret;
switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR:
phydev->interface = PHY_INTERFACE_MODE_10GKR; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX:
phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI:
phydev->interface = PHY_INTERFACE_MODE_10GBASER; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII:
phydev->interface = PHY_INTERFACE_MODE_USXGMII; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI:
phydev->interface = PHY_INTERFACE_MODE_XAUI; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII:
phydev->interface = PHY_INTERFACE_MODE_SGMII; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI:
phydev->interface = PHY_INTERFACE_MODE_RXAUI; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF: default:
phydev->link = false;
phydev->interface = PHY_INTERFACE_MODE_NA; break;
}
/* Read rate from vendor register */ return aqr105_read_rate(phydev);
}
staticint aqr107_read_rate(struct phy_device *phydev)
{
u32 config_reg; int val;
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); if (val < 0) return val;
staticint aqr107_read_status(struct phy_device *phydev)
{ int val, ret;
ret = aqr_read_status(phydev); if (ret) return ret;
if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) return 0;
/* The status register is not immediately correct on line side link up. * Poll periodically until it reflects the correct ON state. * Only return fail for read error, timeout defaults to OFF state.
*/
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PHYXS,
MDIO_PHYXS_VEND_IF_STATUS, val,
(FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val) !=
MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF),
AQR107_OP_IN_PROG_SLEEP,
AQR107_OP_IN_PROG_TIMEOUT, false); if (ret && ret != -ETIMEDOUT) return ret;
switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR:
phydev->interface = PHY_INTERFACE_MODE_10GKR; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX:
phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI:
phydev->interface = PHY_INTERFACE_MODE_10GBASER; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII:
phydev->interface = PHY_INTERFACE_MODE_USXGMII; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI:
phydev->interface = PHY_INTERFACE_MODE_XAUI; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII:
phydev->interface = PHY_INTERFACE_MODE_SGMII; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI:
phydev->interface = PHY_INTERFACE_MODE_RXAUI; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX; break; case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF: default:
phydev->link = false;
phydev->interface = PHY_INTERFACE_MODE_NA; break;
}
/* If we configure settings whilst firmware is still initializing the chip, * then these settings may be overwritten. Therefore make sure chip * initialization has completed. Use presence of the firmware ID as * indicator for initialization having completed. * The chip also provides a "reset completed" bit, but it's cleared after * read. Therefore function would time out if called again.
*/ int aqr_wait_reset_complete(struct phy_device *phydev)
{ int ret, val;
ret = read_poll_timeout(phy_read_mmd, val, val != 0,
AQR_FW_WAIT_SLEEP_US, AQR_FW_WAIT_TIMEOUT_US, false, phydev, MDIO_MMD_VEND1,
VEND1_GLOBAL_FW_ID); if (val < 0) {
phydev_err(phydev, "Failed to read VEND1_GLOBAL_FW_ID: %pe\n",
ERR_PTR(val)); return val;
}
/* Check that the PHY interface type is compatible */ if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
phydev->interface != PHY_INTERFACE_MODE_1000BASEKX &&
phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
phydev->interface != PHY_INTERFACE_MODE_XGMII &&
phydev->interface != PHY_INTERFACE_MODE_USXGMII &&
phydev->interface != PHY_INTERFACE_MODE_10GKR &&
phydev->interface != PHY_INTERFACE_MODE_10GBASER &&
phydev->interface != PHY_INTERFACE_MODE_XAUI &&
phydev->interface != PHY_INTERFACE_MODE_RXAUI) return -ENODEV;
WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n");
ret = aqr_wait_reset_complete(phydev); if (!ret)
aqr107_chip_info(phydev);
ret = aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); if (ret) return ret;
ret = aqr107_config_mdi(phydev); if (ret) return ret;
/* Restore LED polarity state after reset */
for_each_set_bit(led_idx, &priv->leds_active_low, AQR_MAX_LEDS) {
ret = aqr_phy_led_active_low_set(phydev, led_idx, true); if (ret) return ret;
}
for_each_set_bit(led_idx, &priv->leds_active_high, AQR_MAX_LEDS) {
ret = aqr_phy_led_active_low_set(phydev, led_idx, false); if (ret) return ret;
}
return 0;
}
staticint aqcs109_config_init(struct phy_device *phydev)
{ int ret;
/* Check that the PHY interface type is compatible */ if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
phydev->interface != PHY_INTERFACE_MODE_2500BASEX) return -ENODEV;
ret = aqr_wait_reset_complete(phydev); if (!ret)
aqr107_chip_info(phydev);
if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) return;
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); /* call failed or link partner is no Aquantia PHY */ if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) return;
short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH;
downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT;
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); if (val < 0) return;
staticint aqr107_wait_processor_intensive_op(struct phy_device *phydev)
{ int val, err;
/* The datasheet notes to wait at least 1ms after issuing a * processor intensive operation before checking. * We cannot use the 'sleep_before_read' parameter of read_poll_timeout * because that just determines the maximum time slept, not the minimum.
*/
usleep_range(1000, 5000);
staticint aqr107_fill_interface_modes(struct phy_device *phydev)
{ unsignedlong *possible = phydev->possible_interfaces; unsignedint serdes_mode, rate_adapt;
phy_interface_t interface; int i, val;
/* Walk the media-speed configuration registers to determine which * host-side serdes modes may be used by the PHY depending on the * negotiated media speed.
*/ for (i = 0; i < ARRAY_SIZE(aqr_global_cfg_regs); i++) {
val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
aqr_global_cfg_regs[i]); if (val < 0) return val;
if (interface != PHY_INTERFACE_MODE_NA)
__set_bit(interface, possible);
}
return 0;
}
staticint aqr113c_fill_interface_modes(struct phy_device *phydev)
{ int val, ret;
/* It's been observed on some models that - when coming out of suspend * - the FW signals that the PHY is ready but the GLOBAL_CFG registers * continue on returning zeroes for some time. Let's poll the 100M * register until it returns a real value as both 113c and 115c support * this mode.
*/
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
VEND1_GLOBAL_CFG_100M, val, val != 0,
1000, 100000, false); if (ret) return ret;
/* PHY supports speeds up to 2.5G with autoneg. PMA capabilities * are not useful.
*/
linkmode_or(supported, supported, phy_gbit_features);
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, supported);
return 0;
}
staticint aqr111_get_features(struct phy_device *phydev)
{ /* PHY supports speeds up to 5G with autoneg. PMA capabilities * are not useful.
*/
aqr115c_get_features(phydev);
linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
phydev->supported);
return 0;
}
staticint aqr113c_config_init(struct phy_device *phydev)
{ int ret;
ret = aqr107_config_init(phydev); if (ret < 0) return ret;
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
MDIO_PMD_TXDIS_GLOBAL); if (ret) return ret;
ret = aqr107_wait_processor_intensive_op(phydev); if (ret) return ret;
return aqr113c_fill_interface_modes(phydev);
}
staticint aqr107_probe(struct phy_device *phydev)
{ int ret;
phydev->priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct aqr107_priv), GFP_KERNEL); if (!phydev->priv) return -ENOMEM;
ret = aqr_firmware_load(phydev); if (ret) return ret;
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.