drivers/net/ethernet/adi/adin1110.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/adi/adin1110.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/adi/adin1110.c
Extension
.c
Size
43410 bytes
Lines
1741
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 adin1110_netdev_ops = {
	.ndo_open		= adin1110_net_open,
	.ndo_stop		= adin1110_net_stop,
	.ndo_eth_ioctl		= adin1110_ioctl,
	.ndo_start_xmit		= adin1110_start_xmit,
	.ndo_set_mac_address	= adin1110_ndo_set_mac_address,
	.ndo_set_rx_mode	= adin1110_set_rx_mode,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_get_stats64	= adin1110_ndo_get_stats64,
	.ndo_get_port_parent_id	= adin1110_port_get_port_parent_id,
	.ndo_get_phys_port_name	= adin1110_ndo_get_phys_port_name,
};

static void adin1110_get_drvinfo(struct net_device *dev,
				 struct ethtool_drvinfo *di)
{
	strscpy(di->driver, "ADIN1110", sizeof(di->driver));
	strscpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info));
}

static const struct ethtool_ops adin1110_ethtool_ops = {
	.get_drvinfo		= adin1110_get_drvinfo,
	.get_link		= ethtool_op_get_link,
	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
};

static void adin1110_adjust_link(struct net_device *dev)
{
	struct phy_device *phydev = dev->phydev;

	if (!phydev->link)
		phy_print_status(phydev);
}

/* PHY ID is stored in the MAC registers too,
 * check spi connection by reading it.
 */
static int adin1110_check_spi(struct adin1110_priv *priv)
{
	struct gpio_desc *reset_gpio;
	int ret;
	u32 val;

	reset_gpio = devm_gpiod_get_optional(&priv->spidev->dev, "reset",
					     GPIOD_OUT_LOW);
	if (IS_ERR(reset_gpio))
		return dev_err_probe(&priv->spidev->dev, PTR_ERR(reset_gpio),
				     "failed to get reset gpio\n");
	if (reset_gpio) {
		/* MISO pin is used for internal configuration, can't have
		 * anyone else disturbing the SDO line.
		 */
		spi_bus_lock(priv->spidev->controller);

		gpiod_set_value(reset_gpio, 1);
		fsleep(10000);
		gpiod_set_value(reset_gpio, 0);

		/* Need to wait 90 ms before interacting with
		 * the MAC after a HW reset.
		 */
		fsleep(90000);

		spi_bus_unlock(priv->spidev->controller);
	}

	ret = adin1110_read_reg(priv, ADIN1110_PHY_ID, &val);
	if (ret < 0)
		return ret;

	if (val != priv->cfg->phy_id_val) {
		dev_err(&priv->spidev->dev, "PHY ID expected: %x, read: %x\n",
			priv->cfg->phy_id_val, val);
		return -EIO;
	}

	return 0;
}

static int adin1110_hw_forwarding(struct adin1110_priv *priv, bool enable)
{
	int ret;
	int i;

	priv->forwarding = enable;

	if (!priv->forwarding) {
		for (i = ADIN_MAC_FDB_ADDR_SLOT; i < ADIN_MAC_MAX_ADDR_SLOTS; i++) {
			ret = adin1110_clear_mac_address(priv, i);

Annotation

Implementation Notes