drivers/net/ethernet/socionext/netsec.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/socionext/netsec.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/socionext/netsec.c
Extension
.c
Size
58317 bytes
Lines
2231
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 netsec_netdev_ops = {
	.ndo_init		= netsec_netdev_init,
	.ndo_uninit		= netsec_netdev_uninit,
	.ndo_open		= netsec_netdev_open,
	.ndo_stop		= netsec_netdev_stop,
	.ndo_start_xmit		= netsec_netdev_start_xmit,
	.ndo_set_features	= netsec_netdev_set_features,
	.ndo_set_mac_address    = eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= phy_do_ioctl,
	.ndo_xdp_xmit		= netsec_xdp_xmit,
	.ndo_bpf		= netsec_xdp,
};

static int netsec_of_probe(struct platform_device *pdev,
			   struct netsec_priv *priv, u32 *phy_addr)
{
	int err;

	err = of_get_phy_mode(pdev->dev.of_node, &priv->phy_interface);
	if (err) {
		dev_err(&pdev->dev, "missing required property 'phy-mode'\n");
		return err;
	}

	/*
	 * SynQuacer is physically configured with TX and RX delays
	 * but the standard firmware claimed otherwise for a long
	 * time, ignore it.
	 */
	if (of_machine_is_compatible("socionext,developer-box") &&
	    priv->phy_interface != PHY_INTERFACE_MODE_RGMII_ID) {
		dev_warn(&pdev->dev, "Outdated firmware reports incorrect PHY mode, overriding\n");
		priv->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
	}

	priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
	if (!priv->phy_np) {
		dev_err(&pdev->dev, "missing required property 'phy-handle'\n");
		return -EINVAL;
	}

	*phy_addr = of_mdio_parse_addr(&pdev->dev, priv->phy_np);

	priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */
	if (IS_ERR(priv->clk))
		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk),
				     "phy_ref_clk not found\n");
	priv->freq = clk_get_rate(priv->clk);

	return 0;
}

static int netsec_acpi_probe(struct platform_device *pdev,
			     struct netsec_priv *priv, u32 *phy_addr)
{
	int ret;

	if (!IS_ENABLED(CONFIG_ACPI))
		return -ENODEV;

	/* ACPI systems are assumed to configure the PHY in firmware, so
	 * there is really no need to discover the PHY mode from the DSDT.
	 * Since firmware is known to exist in the field that configures the
	 * PHY correctly but passes the wrong mode string in the phy-mode
	 * device property, we have no choice but to ignore it.
	 */
	priv->phy_interface = PHY_INTERFACE_MODE_NA;

	ret = device_property_read_u32(&pdev->dev, "phy-channel", phy_addr);
	if (ret)
		return dev_err_probe(&pdev->dev, ret,
				     "missing required property 'phy-channel'\n");

	ret = device_property_read_u32(&pdev->dev,
				       "socionext,phy-clock-frequency",
				       &priv->freq);
	if (ret)
		return dev_err_probe(&pdev->dev, ret,
				     "missing required property 'socionext,phy-clock-frequency'\n");
	return 0;
}

static void netsec_unregister_mdio(struct netsec_priv *priv)
{
	struct phy_device *phydev = priv->phydev;

	if (!dev_of_node(priv->dev) && phydev) {
		phy_device_remove(phydev);
		phy_device_free(phydev);

Annotation

Implementation Notes