drivers/net/ethernet/arc/emac_main.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/arc/emac_main.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/arc/emac_main.c
Extension
.c
Size
26926 bytes
Lines
1044
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops arc_emac_netdev_ops = {
	.ndo_open		= arc_emac_open,
	.ndo_stop		= arc_emac_stop,
	.ndo_start_xmit		= arc_emac_tx,
	.ndo_set_mac_address	= arc_emac_set_address,
	.ndo_get_stats		= arc_emac_stats,
	.ndo_set_rx_mode	= arc_emac_set_rx_mode,
	.ndo_eth_ioctl		= phy_do_ioctl_running,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= arc_emac_poll_controller,
#endif
};

int arc_emac_probe(struct net_device *ndev, int interface)
{
	struct device *dev = ndev->dev.parent;
	struct resource res_regs;
	struct device_node *phy_node;
	struct phy_device *phydev = NULL;
	struct arc_emac_priv *priv;
	unsigned int id, clock_frequency, irq;
	int err;

	/* Get PHY from device tree */
	phy_node = of_parse_phandle(dev->of_node, "phy", 0);
	if (!phy_node) {
		dev_err(dev, "failed to retrieve phy description from device tree\n");
		return -ENODEV;
	}

	/* Get EMAC registers base address from device tree */
	err = of_address_to_resource(dev->of_node, 0, &res_regs);
	if (err) {
		dev_err(dev, "failed to retrieve registers base from device tree\n");
		err = -ENODEV;
		goto out_put_node;
	}

	/* Get IRQ from device tree */
	irq = irq_of_parse_and_map(dev->of_node, 0);
	if (!irq) {
		dev_err(dev, "failed to retrieve <irq> value from device tree\n");
		err = -ENODEV;
		goto out_put_node;
	}

	ndev->netdev_ops = &arc_emac_netdev_ops;
	ndev->ethtool_ops = &arc_emac_ethtool_ops;
	ndev->watchdog_timeo = TX_TIMEOUT;

	priv = netdev_priv(ndev);
	priv->dev = dev;

	priv->regs = devm_ioremap_resource(dev, &res_regs);
	if (IS_ERR(priv->regs)) {
		err = PTR_ERR(priv->regs);
		goto out_put_node;
	}

	dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs);

	if (priv->clk) {
		err = clk_prepare_enable(priv->clk);
		if (err) {
			dev_err(dev, "failed to enable clock\n");
			goto out_put_node;
		}

		clock_frequency = clk_get_rate(priv->clk);
	} else {
		/* Get CPU clock frequency from device tree */
		if (of_property_read_u32(dev->of_node, "clock-frequency",
					 &clock_frequency)) {
			dev_err(dev, "failed to retrieve <clock-frequency> from device tree\n");
			err = -EINVAL;
			goto out_put_node;
		}
	}

	id = arc_reg_get(priv, R_ID);

	/* Check for EMAC revision 5 or 7, magic number */
	if (!(id == 0x0005fd02 || id == 0x0007fd02)) {
		dev_err(dev, "ARC EMAC not detected, id=0x%x\n", id);
		err = -ENODEV;
		goto out_clken;
	}
	dev_info(dev, "ARC EMAC detected with id: 0x%x\n", id);

	/* Set poll rate so that it polls every 1 ms */

Annotation

Implementation Notes