drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
Extension
.c
Size
38548 bytes
Lines
1491
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 bcmasp_netdev_ops = {
	.ndo_open		= bcmasp_open,
	.ndo_stop		= bcmasp_stop,
	.ndo_start_xmit		= bcmasp_xmit,
	.ndo_tx_timeout		= bcmasp_tx_timeout,
	.ndo_set_rx_mode	= bcmasp_set_rx_mode,
	.ndo_get_phys_port_name	= bcmasp_get_phys_port_name,
	.ndo_eth_ioctl		= phy_do_ioctl_running,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_get_stats64	= bcmasp_get_stats64,
};

static void bcmasp_map_res(struct bcmasp_priv *priv, struct bcmasp_intf *intf)
{
	/* Per port */
	intf->res.umac = priv->base + UMC_OFFSET(intf);
	intf->res.umac2fb = priv->base + (UMAC2FB_OFFSET + priv->rx_ctrl_offset +
					  (intf->port * 0x4));
	intf->res.rgmii = priv->base + RGMII_OFFSET(intf);

	/* Per ch */
	intf->tx_spb_dma = priv->base + TX_SPB_DMA_OFFSET(intf);
	intf->res.tx_spb_ctrl = priv->base + TX_SPB_CTRL_OFFSET(intf);
	intf->res.tx_spb_top = priv->base + TX_SPB_TOP_OFFSET(intf);
	intf->res.tx_epkt_core = priv->base + TX_EPKT_C_OFFSET(intf);
	intf->res.tx_pause_ctrl = priv->base + TX_PAUSE_CTRL_OFFSET(intf);

	intf->rx_edpkt_dma = priv->base + RX_EDPKT_DMA_OFFSET(intf);
	intf->rx_edpkt_cfg = priv->base + RX_EDPKT_CFG_OFFSET(intf);
}

struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv,
					    struct device_node *ndev_dn, int i)
{
	struct device *dev = &priv->pdev->dev;
	struct bcmasp_intf *intf;
	struct net_device *ndev;
	int ch, port, ret;

	if (of_property_read_u32(ndev_dn, "reg", &port)) {
		dev_warn(dev, "%s: invalid port number\n", ndev_dn->name);
		goto err;
	}

	if (of_property_read_u32(ndev_dn, "brcm,channel", &ch)) {
		dev_warn(dev, "%s: invalid ch number\n", ndev_dn->name);
		goto err;
	}

	ndev = alloc_etherdev(sizeof(struct bcmasp_intf));
	if (!ndev) {
		dev_warn(dev, "%s: unable to alloc ndev\n", ndev_dn->name);
		goto err;
	}
	intf = netdev_priv(ndev);

	intf->parent = priv;
	intf->ndev = ndev;
	intf->channel = ch;
	intf->port = port;
	intf->ndev_dn = ndev_dn;
	intf->index = i;

	ret = of_get_phy_mode(ndev_dn, &intf->phy_interface);
	if (ret < 0) {
		dev_err(dev, "invalid PHY mode property\n");
		goto err_free_netdev;
	}

	if (intf->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
		intf->internal_phy = true;

	intf->phy_dn = of_parse_phandle(ndev_dn, "phy-handle", 0);
	if (!intf->phy_dn && of_phy_is_fixed_link(ndev_dn)) {
		ret = of_phy_register_fixed_link(ndev_dn);
		if (ret) {
			dev_warn(dev, "%s: failed to register fixed PHY\n",
				 ndev_dn->name);
			goto err_free_netdev;
		}
		intf->phy_dn = ndev_dn;
	}

	/* Map resource */
	bcmasp_map_res(priv, intf);

	if ((!phy_interface_mode_is_rgmii(intf->phy_interface) &&
	     intf->phy_interface != PHY_INTERFACE_MODE_MII &&
	     intf->phy_interface != PHY_INTERFACE_MODE_INTERNAL) ||
	    (intf->port != 1 && intf->internal_phy)) {

Annotation

Implementation Notes