drivers/net/phy/adin1100.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/adin1100.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/adin1100.c
Extension
.c
Size
8791 bytes
Lines
355
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct adin_mse_sqi_range {
	u16 start;
	u16 end;
};

static const struct adin_mse_sqi_range adin_mse_sqi_map[] = {
	{ 0x0A74, 0xFFFF },
	{ 0x084E, 0x0A74 },
	{ 0x0698, 0x084E },
	{ 0x053D, 0x0698 },
	{ 0x0429, 0x053D },
	{ 0x034E, 0x0429 },
	{ 0x02A0, 0x034E },
	{ 0x0000, 0x02A0 },
};

/**
 * struct adin_priv - ADIN PHY driver private data
 * @tx_level_2v4_able:		set if the PHY supports 2.4V TX levels (10BASE-T1L)
 * @tx_level_2v4:		set if the PHY requests 2.4V TX levels (10BASE-T1L)
 * @tx_level_prop_present:	set if the TX level is specified in DT
 */
struct adin_priv {
	unsigned int		tx_level_2v4_able:1;
	unsigned int		tx_level_2v4:1;
	unsigned int		tx_level_prop_present:1;
};

static int adin_read_status(struct phy_device *phydev)
{
	int ret;

	ret = genphy_c45_read_status(phydev);
	if (ret)
		return ret;

	ret = phy_read_mmd(phydev, MDIO_MMD_AN, ADIN_AN_PHY_INST_STATUS);
	if (ret < 0)
		return ret;

	if (ret & ADIN_IS_CFG_SLV)
		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;

	if (ret & ADIN_IS_CFG_MST)
		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;

	return 0;
}

static int adin_config_aneg(struct phy_device *phydev)
{
	struct adin_priv *priv = phydev->priv;
	int ret;

	if (phydev->autoneg == AUTONEG_DISABLE) {
		ret = genphy_c45_pma_setup_forced(phydev);
		if (ret < 0)
			return ret;

		if (priv->tx_level_prop_present && priv->tx_level_2v4)
			ret = phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
					       MDIO_PMA_10T1L_CTRL_2V4_EN);
		else
			ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
						 MDIO_PMA_10T1L_CTRL_2V4_EN);
		if (ret < 0)
			return ret;

		/* Force PHY to use above configurations */
		return phy_set_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
	}

	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
	if (ret < 0)
		return ret;

	/* Request increased transmit level from LP. */
	if (priv->tx_level_prop_present && priv->tx_level_2v4) {
		ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
				       MDIO_AN_T1_ADV_H_10L_TX_HI |
				       MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
		if (ret < 0)
			return ret;
	}

	/* Disable 2.4 Vpp transmit level. */
	if ((priv->tx_level_prop_present && !priv->tx_level_2v4) || !priv->tx_level_2v4_able) {
		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
					 MDIO_AN_T1_ADV_H_10L_TX_HI |
					 MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);

Annotation

Implementation Notes