drivers/net/ethernet/broadcom/genet/bcmmii.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/genet/bcmmii.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/genet/bcmmii.c
Extension
.c
Size
16050 bytes
Lines
619
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

if (priv->autoneg_pause) {
			bool tx_pause = 0, rx_pause = 0;

			if (phydev->autoneg)
				phy_get_pause(phydev, &tx_pause, &rx_pause);

			if (!tx_pause)
				cmd_bits |= CMD_TX_PAUSE_IGNORE;
			if (!rx_pause)
				cmd_bits |= CMD_RX_PAUSE_IGNORE;
		}

		/* Manual override */
		if (!priv->rx_pause)
			cmd_bits |= CMD_RX_PAUSE_IGNORE;
		if (!priv->tx_pause)
			cmd_bits |= CMD_TX_PAUSE_IGNORE;
	}

	/* Program UMAC and RGMII block based on established
	 * link speed, duplex, and pause. The speed set in
	 * umac->cmd tell RGMII block which clock to use for
	 * transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
	 * Receive clock is provided by the PHY.
	 */
	reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
	reg |= RGMII_LINK;
	bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);

	spin_lock_bh(&priv->reg_lock);
	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
	reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
		       CMD_HD_EN |
		       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
	reg |= cmd_bits;
	if (reg & CMD_SW_RESET) {
		reg &= ~CMD_SW_RESET;
		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
		udelay(2);
		reg |= CMD_TX_EN | CMD_RX_EN;
	}
	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
	spin_unlock_bh(&priv->reg_lock);

}

/* setup netdev link state when PHY link status change and
 * update UMAC and RGMII block when link up
 */
void bcmgenet_mii_setup(struct net_device *dev)
{
	struct bcmgenet_priv *priv = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	u32 reg;

	if (phydev->link) {
		bcmgenet_mac_config(dev);
	} else {
		reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
		reg &= ~RGMII_LINK;
		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
	}

	bcmgenet_eee_enable_set(dev, phydev->enable_tx_lpi);

	phy_print_status(phydev);
}


static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
					  struct fixed_phy_status *status)
{
	struct bcmgenet_priv *priv;
	u32 reg;

	if (dev && dev->phydev && status) {
		priv = netdev_priv(dev);
		reg = bcmgenet_umac_readl(priv, UMAC_MODE);
		status->link = !!(reg & MODE_LINK_STATUS);
	}

	return 0;
}

void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx)
{
	struct phy_device *phydev = dev->phydev;

	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising, rx);
	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising,

Annotation

Implementation Notes