drivers/net/can/sun4i_can.c

Source file repositories/reference/linux-study-clean/drivers/net/can/sun4i_can.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/sun4i_can.c
Extension
.c
Size
26036 bytes
Lines
930
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 sun4ican_netdev_ops = {
	.ndo_open = sun4ican_open,
	.ndo_stop = sun4ican_close,
	.ndo_start_xmit = sun4ican_start_xmit,
};

static const struct ethtool_ops sun4ican_ethtool_ops = {
	.get_ts_info = ethtool_op_get_ts_info,
};

static const struct sun4ican_quirks sun4ican_quirks_a10 = {
	.has_reset = false,
	.acp_offset = 0,
};

static const struct sun4ican_quirks sun4ican_quirks_r40 = {
	.has_reset = true,
	.acp_offset = 0,
};

static const struct sun4ican_quirks sun4ican_quirks_d1 = {
	.has_reset = true,
	.acp_offset = (SUN4I_REG_ACPC_ADDR_D1 - SUN4I_REG_ACPC_ADDR),
};

static const struct of_device_id sun4ican_of_match[] = {
	{
		.compatible = "allwinner,sun4i-a10-can",
		.data = &sun4ican_quirks_a10
	}, {
		.compatible = "allwinner,sun7i-a20-can",
		.data = &sun4ican_quirks_a10
	}, {
		.compatible = "allwinner,sun8i-r40-can",
		.data = &sun4ican_quirks_r40
	}, {
		.compatible = "allwinner,sun20i-d1-can",
		.data = &sun4ican_quirks_d1
	}, {
		/* sentinel */
	},
};

MODULE_DEVICE_TABLE(of, sun4ican_of_match);

static void sun4ican_remove(struct platform_device *pdev)
{
	struct net_device *dev = platform_get_drvdata(pdev);

	unregister_netdev(dev);
	free_candev(dev);
}

static int sun4ican_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct clk *clk;
	struct reset_control *reset = NULL;
	void __iomem *addr;
	int err, irq;
	struct net_device *dev;
	struct sun4ican_priv *priv;
	const struct sun4ican_quirks *quirks;

	quirks = of_device_get_match_data(&pdev->dev);
	if (!quirks) {
		dev_err(&pdev->dev, "failed to determine the quirks to use\n");
		err = -ENODEV;
		goto exit;
	}

	if (quirks->has_reset) {
		reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
		if (IS_ERR(reset)) {
			dev_err(&pdev->dev, "unable to request reset\n");
			err = PTR_ERR(reset);
			goto exit;
		}
	}

	clk = of_clk_get(np, 0);
	if (IS_ERR(clk)) {
		dev_err(&pdev->dev, "unable to request clock\n");
		err = -ENODEV;
		goto exit;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		err = -ENODEV;

Annotation

Implementation Notes