drivers/net/ethernet/marvell/mv643xx_eth.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/mv643xx_eth.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/mv643xx_eth.c
Extension
.c
Size
81374 bytes
Lines
3332
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 mv643xx_eth_netdev_ops = {
	.ndo_open		= mv643xx_eth_open,
	.ndo_stop		= mv643xx_eth_stop,
	.ndo_start_xmit		= mv643xx_eth_xmit,
	.ndo_set_rx_mode	= mv643xx_eth_set_rx_mode,
	.ndo_set_mac_address	= mv643xx_eth_set_mac_address,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= mv643xx_eth_ioctl,
	.ndo_change_mtu		= mv643xx_eth_change_mtu,
	.ndo_set_features	= mv643xx_eth_set_features,
	.ndo_tx_timeout		= mv643xx_eth_tx_timeout,
	.ndo_get_stats		= mv643xx_eth_get_stats,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= mv643xx_eth_netpoll,
#endif
};

static int mv643xx_eth_probe(struct platform_device *pdev)
{
	struct mv643xx_eth_platform_data *pd;
	struct mv643xx_eth_private *mp;
	struct net_device *dev;
	struct phy_device *phydev = NULL;
	u32 psc1r;
	int err, irq;

	pd = dev_get_platdata(&pdev->dev);
	if (pd == NULL) {
		dev_err(&pdev->dev, "no mv643xx_eth_platform_data\n");
		return -ENODEV;
	}

	if (pd->shared == NULL) {
		dev_err(&pdev->dev, "no mv643xx_eth_platform_data->shared\n");
		return -ENODEV;
	}

	dev = alloc_etherdev_mq(sizeof(struct mv643xx_eth_private), 8);
	if (!dev)
		return -ENOMEM;

	SET_NETDEV_DEV(dev, &pdev->dev);
	mp = netdev_priv(dev);
	platform_set_drvdata(pdev, mp);

	mp->shared = platform_get_drvdata(pd->shared);
	mp->base = mp->shared->base + 0x0400 + (pd->port_number << 10);
	mp->port_num = pd->port_number;

	mp->dev = dev;

	if (of_device_is_compatible(pdev->dev.of_node,
				    "marvell,kirkwood-eth-port")) {
		psc1r = rdlp(mp, PORT_SERIAL_CONTROL1);

		/* Kirkwood resets some registers on gated clocks. Especially
		 * CLK125_BYPASS_EN must be cleared but is not available on
		 * all other SoCs/System Controllers using this driver.
		 */
		psc1r &= ~CLK125_BYPASS_EN;

		/* On Kirkwood with two Ethernet controllers, if both of them
		 * have RGMII_EN disabled, the first controller will be in GMII
		 * mode and the second one is effectively disabled, instead of
		 * two MII interfaces.
		 *
		 * To enable GMII in the first controller, the second one must
		 * also be configured (and may be enabled) with RGMII_EN
		 * disabled too, even though it cannot be used at all.
		 */
		switch (pd->interface) {
		/* Use internal to denote second controller being disabled */
		case PHY_INTERFACE_MODE_INTERNAL:
		case PHY_INTERFACE_MODE_MII:
		case PHY_INTERFACE_MODE_GMII:
			psc1r &= ~RGMII_EN;
			break;
		case PHY_INTERFACE_MODE_RGMII:
		case PHY_INTERFACE_MODE_RGMII_ID:
		case PHY_INTERFACE_MODE_RGMII_RXID:
		case PHY_INTERFACE_MODE_RGMII_TXID:
			psc1r |= RGMII_EN;
			break;
		default:
			/* Unknown; don't touch */
			break;
		}

		wrlp(mp, PORT_SERIAL_CONTROL1, psc1r);
	}

Annotation

Implementation Notes