drivers/net/ethernet/freescale/fec_mpc52xx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/freescale/fec_mpc52xx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/freescale/fec_mpc52xx.c
Extension
.c
Size
28441 bytes
Lines
1082
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 mpc52xx_fec_netdev_ops = {
	.ndo_open = mpc52xx_fec_open,
	.ndo_stop = mpc52xx_fec_close,
	.ndo_start_xmit = mpc52xx_fec_start_xmit,
	.ndo_set_rx_mode = mpc52xx_fec_set_multicast_list,
	.ndo_set_mac_address = mpc52xx_fec_set_mac_address,
	.ndo_validate_addr = eth_validate_addr,
	.ndo_eth_ioctl = phy_do_ioctl,
	.ndo_tx_timeout = mpc52xx_fec_tx_timeout,
	.ndo_get_stats = mpc52xx_fec_get_stats,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller = mpc52xx_fec_poll_controller,
#endif
};

/* ======================================================================== */
/* OF Driver                                                                */
/* ======================================================================== */

static int mpc52xx_fec_probe(struct platform_device *op)
{
	int rv;
	struct net_device *ndev;
	struct mpc52xx_fec_priv *priv = NULL;
	struct resource mem;
	const u32 *prop;
	int prop_size;
	struct device_node *np = op->dev.of_node;

	phys_addr_t rx_fifo;
	phys_addr_t tx_fifo;

	/* Get the ether ndev & it's private zone */
	ndev = alloc_etherdev(sizeof(struct mpc52xx_fec_priv));
	if (!ndev)
		return -ENOMEM;

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

	/* Reserve FEC control zone */
	rv = of_address_to_resource(np, 0, &mem);
	if (rv) {
		pr_err("Error while parsing device node resource\n");
		goto err_netdev;
	}
	if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) {
		pr_err("invalid resource size (%lx < %x), check mpc52xx_devices.c\n",
		       (unsigned long)resource_size(&mem),
		       sizeof(struct mpc52xx_fec));
		rv = -EINVAL;
		goto err_netdev;
	}

	if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec),
				DRIVER_NAME)) {
		rv = -EBUSY;
		goto err_netdev;
	}

	/* Init ether ndev with what we have */
	ndev->netdev_ops	= &mpc52xx_fec_netdev_ops;
	ndev->ethtool_ops	= &mpc52xx_fec_ethtool_ops;
	ndev->watchdog_timeo	= FEC_WATCHDOG_TIMEOUT;
	ndev->base_addr		= mem.start;
	SET_NETDEV_DEV(ndev, &op->dev);

	spin_lock_init(&priv->lock);

	/* ioremap the zones */
	priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec));

	if (!priv->fec) {
		rv = -ENOMEM;
		goto err_mem_region;
	}

	/* Bestcomm init */
	rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data);
	tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data);

	priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE);
	priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo);

	if (!priv->rx_dmatsk || !priv->tx_dmatsk) {
		pr_err("Can not init SDMA tasks\n");
		rv = -ENOMEM;
		goto err_rx_tx_dmatsk;
	}

Annotation

Implementation Notes