drivers/net/ethernet/allwinner/sun4i-emac.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/allwinner/sun4i-emac.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/allwinner/sun4i-emac.c
Extension
.c
Size
28895 bytes
Lines
1156
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 emac_netdev_ops = {
	.ndo_open		= emac_open,
	.ndo_stop		= emac_stop,
	.ndo_start_xmit		= emac_start_xmit,
	.ndo_tx_timeout		= emac_timeout,
	.ndo_set_rx_mode	= emac_set_rx_mode,
	.ndo_eth_ioctl		= phy_do_ioctl_running,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= emac_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= emac_poll_controller,
#endif
};

static int emac_configure_dma(struct emac_board_info *db)
{
	struct platform_device *pdev = db->pdev;
	struct net_device *ndev = db->ndev;
	struct dma_slave_config conf = {};
	struct resource *regs;
	int err = 0;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!regs) {
		netdev_err(ndev, "get io resource from device failed.\n");
		err = -ENOMEM;
		goto out_clear_chan;
	}

	netdev_info(ndev, "get io resource from device: %pa, size = %u\n",
		    &regs->start, (unsigned int)resource_size(regs));
	db->emac_rx_fifo = regs->start + EMAC_RX_IO_DATA_REG;

	db->rx_chan = dma_request_chan(&pdev->dev, "rx");
	if (IS_ERR(db->rx_chan)) {
		netdev_err(ndev,
			   "failed to request dma channel. dma is disabled\n");
		err = PTR_ERR(db->rx_chan);
		goto out_clear_chan;
	}

	conf.direction = DMA_DEV_TO_MEM;
	conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	conf.src_addr = db->emac_rx_fifo;
	conf.dst_maxburst = 4;
	conf.src_maxburst = 4;
	conf.device_fc = false;

	err = dmaengine_slave_config(db->rx_chan, &conf);
	if (err) {
		netdev_err(ndev, "config dma slave failed\n");
		err = -EINVAL;
		goto out_slave_configure_err;
	}

	return err;

out_slave_configure_err:
	dma_release_channel(db->rx_chan);

out_clear_chan:
	db->rx_chan = NULL;
	return err;
}

/* Search EMAC board, allocate space and register it
 */
static int emac_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct emac_board_info *db;
	struct net_device *ndev;
	int ret = 0;

	ndev = alloc_etherdev(sizeof(struct emac_board_info));
	if (!ndev) {
		dev_err(&pdev->dev, "could not allocate device.\n");
		return -ENOMEM;
	}

	SET_NETDEV_DEV(ndev, &pdev->dev);

	db = netdev_priv(ndev);

	db->dev = &pdev->dev;
	db->ndev = ndev;
	db->pdev = pdev;
	db->msg_enable = netif_msg_init(debug, EMAC_DEFAULT_MSG_ENABLE);

Annotation

Implementation Notes