/* AT803x supports either the XTAL input pad, an internal PLL or the * DSP as clock reference for the clock output pad. The XTAL reference * is only used for 25 MHz output, all other frequencies need the PLL. * The DSP as a clock reference is used in synchronous ethernet * applications. * * By default the PLL is only enabled if there is a link. Otherwise * the PHY will go into low power state and disabled the PLL. You can * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always * enabled.
*/ #define AT803X_MMD7_CLK25M 0x8016 #define AT803X_CLK_OUT_MASK GENMASK(4, 2) #define AT803X_CLK_OUT_25MHZ_XTAL 0 #define AT803X_CLK_OUT_25MHZ_DSP 1 #define AT803X_CLK_OUT_50MHZ_PLL 2 #define AT803X_CLK_OUT_50MHZ_DSP 3 #define AT803X_CLK_OUT_62_5MHZ_PLL 4 #define AT803X_CLK_OUT_62_5MHZ_DSP 5 #define AT803X_CLK_OUT_125MHZ_PLL 6 #define AT803X_CLK_OUT_125MHZ_DSP 7
/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask * but doesn't support choosing between XTAL/PLL and DSP.
*/ #define AT8035_CLK_OUT_MASK GENMASK(4, 3)
ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq); if (!ret) { switch (freq) { case 25000000:
sel = AT803X_CLK_OUT_25MHZ_XTAL; break; case 50000000:
sel = AT803X_CLK_OUT_50MHZ_PLL; break; case 62500000:
sel = AT803X_CLK_OUT_62_5MHZ_PLL; break; case 125000000:
sel = AT803X_CLK_OUT_125MHZ_PLL; break; default:
phydev_err(phydev, "invalid qca,clk-out-frequency\n"); return -EINVAL;
}
err = genphy_read_abilities(phydev); if (err) return err;
if (phydev->drv->phy_id != ATH8031_PHY_ID) return 0;
/* AR8031/AR8033 have different status registers * for copper and fiber operation. However, the * extended status register is the same for both * operation modes. * * As a result of that, ESTATUS_1000_XFULL is set * to 1 even when operating in copper TP mode. * * Remove this mode from the supported link modes * when not operating in 1000BaseX mode.
*/ if (!priv->is_1000basex)
linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->supported);
return 0;
}
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) return 0;
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 * values are retained.
*/ 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 * software reset, the value is retained.
*/ if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE) &&
!(phydev->dev_flags & PHY_F_RXC_ALWAYS_ON)) return 0;
staticint at803x_config_init(struct phy_device *phydev)
{ int ret;
/* The RX and TX delay default is: * after HW reset: RX delay enabled and TX delay disabled * after SW reset: RX delay enabled, while TX delay retains the * value before reset.
*/ 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 * multigig switches read this bit and attempt to negotiate 10Gbps * rates even if the next page bit is disabled. This is incorrect * behaviour but we still need to accommodate it. XNP is only needed * for 10Gbps support, so disable XNP.
*/ return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0);
}
staticvoid at803x_link_change_notify(struct phy_device *phydev)
{ /* * Conduct a hardware reset for AT8030 every time a link loss is * signalled. This is necessary to circumvent a hardware bug that * occurs when the cable is unplugged while TX packets are pending * in the FIFO. In such cases, the FIFO enters an error mode it * cannot recover from by software.
*/ if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) { struct at803x_context context;
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));
}
return 1;
}
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 * there is no link partner or when the link partner is * auto-negotiating. Starting the test will restart the AN * automatically. It seems that doing this repeatedly we will * get a slot where our link partner won't disturb our * 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;
return 0;
}
staticvoid at803x_cable_test_autoneg(struct phy_device *phydev)
{ /* Enable auto-negotiation, but advertise no capabilities, no link * will be established. A restart of the auto-negotiation is not * required, because the cable test will automatically break the link.
*/
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 */ return 0;
}
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. * Mask out non-supported modes so the correct interface is picked.
*/
linkmode_and(sfp_support, phy_support, sfp_support);
/* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes * interface for use with SFP modules. * However, some copper modules detected as having a preferred SGMII * interface do default to and function in 1000Base-X mode, so just * print a warning and allow such modules, as they may have some chance * of working.
*/ 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 * by default
*/ return phy_modify_mmd(phydev, MDIO_MMD_PCS,
AT803X_PHY_MMD3_WOL_CTRL,
AT803X_WOL_EN, 0);
}
/* Some bootloaders leave the fiber page selected. * Switch to the appropriate page (fiber or copper), as otherwise we * read the PHY capabilities from the wrong page.
*/
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 */ return 0;
}
/* 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 * if property is set. Assume property is set * with the mask not zero.
*/ if (priv->clk_25m_mask) { /* Fixup for the AR8030/AR8035. This chip has another mask and * doesn't support the DSP reference. Eg. the lowest bit of the * mask. The upper two bits select the same frequencies. Mask * the lowest bit here. * * Warning: * There was no datasheet for the AR8030 available so this is * just a guess. But the AR8035 is listed as pin compatible * to the AR8030 so there might be a good chance it works on * the AR8030 too.
*/
priv->clk_25m_reg &= AT8035_CLK_OUT_MASK;
priv->clk_25m_mask &= AT8035_CLK_OUT_MASK;
}
return 0;
}
/* AR8030 and AR8035 shared the same special mask for clk_25m */ staticint at8035_probe(struct phy_device *phydev)
{ int ret;
/* * set LDO efuse: first temporarily store ANA_DAC_FILTER value from * debug register as it will be reset once the ANA_LDO_EFUSE register * is written to
*/
val = at803x_debug_reg_read(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER);
at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE,
IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK,
IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT);
at803x_debug_reg_write(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER, val);
/* set 8023AZ EEE TX and RX timer values */
phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_EEE_TX_TIMER,
IPQ5018_PHY_PCS_EEE_TX_TIMER_VAL);
phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_EEE_RX_TIMER,
IPQ5018_PHY_PCS_EEE_RX_TIMER_VAL);
/* 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);
}
return 0;
}
staticvoid ipq5018_link_change_notify(struct phy_device *phydev)
{ /* * Reset the FIFO buffer upon link disconnects to clear any residual data * which may cause issues with the FIFO which it cannot recover from.
*/
mdiobus_modify_changed(phydev->mdio.bus, phydev->mdio.addr,
IPQ5018_PHY_FIFO_CONTROL, IPQ5018_PHY_FIFO_RESET,
phydev->link ? IPQ5018_PHY_FIFO_RESET : 0);
}
¤ 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.0.21Bemerkung:
(vorverarbeitet)
¤
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.