drivers/net/ethernet/nxp/lpc_eth.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/nxp/lpc_eth.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/nxp/lpc_eth.c
Extension
.c
Size
40962 bytes
Lines
1523
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 lpc_netdev_ops = {
	.ndo_open		= lpc_eth_open,
	.ndo_stop		= lpc_eth_close,
	.ndo_start_xmit		= lpc_eth_hard_start_xmit,
	.ndo_set_rx_mode	= lpc_eth_set_multicast_list,
	.ndo_eth_ioctl		= phy_do_ioctl_running,
	.ndo_set_mac_address	= lpc_set_mac_address,
	.ndo_validate_addr	= eth_validate_addr,
};

static int lpc_eth_drv_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct netdata_local *pldat;
	struct net_device *ndev;
	dma_addr_t dma_handle;
	struct resource *res;
	u8 addr[ETH_ALEN];
	int irq, ret;

	/* Setup network interface for RMII or MII mode */
	lpc32xx_set_phy_interface_mode(lpc_phy_interface_mode(dev));

	/* Get platform resources */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(pdev, 0);
	if (!res || irq < 0) {
		dev_err(dev, "error getting resources.\n");
		ret = -ENXIO;
		goto err_exit;
	}

	/* Allocate net driver data structure */
	ndev = alloc_etherdev(sizeof(struct netdata_local));
	if (!ndev) {
		dev_err(dev, "could not allocate device.\n");
		ret = -ENOMEM;
		goto err_exit;
	}

	SET_NETDEV_DEV(ndev, dev);

	pldat = netdev_priv(ndev);
	pldat->pdev = pdev;
	pldat->ndev = ndev;

	spin_lock_init(&pldat->lock);

	/* Save resources */
	ndev->irq = irq;

	/* Get clock for the device */
	pldat->clk = clk_get(dev, NULL);
	if (IS_ERR(pldat->clk)) {
		dev_err(dev, "error getting clock.\n");
		ret = PTR_ERR(pldat->clk);
		goto err_out_free_dev;
	}

	/* Enable network clock */
	ret = clk_prepare_enable(pldat->clk);
	if (ret)
		goto err_out_clk_put;

	/* Map IO space */
	pldat->net_base = ioremap(res->start, resource_size(res));
	if (!pldat->net_base) {
		dev_err(dev, "failed to map registers\n");
		ret = -ENOMEM;
		goto err_out_disable_clocks;
	}
	ret = request_irq(ndev->irq, __lpc_eth_interrupt, 0,
			  ndev->name, ndev);
	if (ret) {
		dev_err(dev, "error requesting interrupt.\n");
		goto err_out_iounmap;
	}

	/* Setup driver functions */
	ndev->netdev_ops = &lpc_netdev_ops;
	ndev->ethtool_ops = &lpc_eth_ethtool_ops;
	ndev->watchdog_timeo = msecs_to_jiffies(2500);

	/* Get size of DMA buffers/descriptors region */
	pldat->dma_buff_size = (ENET_TX_DESC + ENET_RX_DESC) * (ENET_MAXF_SIZE +
		sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t));

	if (use_iram_for_net(dev)) {
		if (pldat->dma_buff_size >

Annotation

Implementation Notes