drivers/net/can/ti_hecc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/ti_hecc.c
Extension
.c
Size
31091 bytes
Lines
1038
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 ti_hecc_netdev_ops = {
	.ndo_open		= ti_hecc_open,
	.ndo_stop		= ti_hecc_close,
	.ndo_start_xmit		= ti_hecc_xmit,
};

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

static const struct of_device_id ti_hecc_dt_ids[] = {
	{
		.compatible = "ti,am3517-hecc",
	},
	{ }
};
MODULE_DEVICE_TABLE(of, ti_hecc_dt_ids);

static int ti_hecc_probe(struct platform_device *pdev)
{
	struct net_device *ndev = (struct net_device *)0;
	struct ti_hecc_priv *priv;
	struct device_node *np = pdev->dev.of_node;
	struct regulator *reg_xceiver;
	int err = -ENODEV;

	if (!IS_ENABLED(CONFIG_OF) || !np)
		return -EINVAL;

	reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
	if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
		return -EPROBE_DEFER;
	else if (IS_ERR(reg_xceiver))
		reg_xceiver = NULL;

	ndev = alloc_candev(sizeof(struct ti_hecc_priv), HECC_MAX_TX_MBOX);
	if (!ndev) {
		dev_err(&pdev->dev, "alloc_candev failed\n");
		return -ENOMEM;
	}
	priv = netdev_priv(ndev);

	/* handle hecc memory */
	priv->base = devm_platform_ioremap_resource_byname(pdev, "hecc");
	if (IS_ERR(priv->base)) {
		dev_err(&pdev->dev, "hecc ioremap failed\n");
		err = PTR_ERR(priv->base);
		goto probe_exit_candev;
	}

	/* handle hecc-ram memory */
	priv->hecc_ram = devm_platform_ioremap_resource_byname(pdev,
							       "hecc-ram");
	if (IS_ERR(priv->hecc_ram)) {
		dev_err(&pdev->dev, "hecc-ram ioremap failed\n");
		err = PTR_ERR(priv->hecc_ram);
		goto probe_exit_candev;
	}

	/* handle mbx memory */
	priv->mbx = devm_platform_ioremap_resource_byname(pdev, "mbx");
	if (IS_ERR(priv->mbx)) {
		dev_err(&pdev->dev, "mbx ioremap failed\n");
		err = PTR_ERR(priv->mbx);
		goto probe_exit_candev;
	}

	ndev->irq = platform_get_irq(pdev, 0);
	if (ndev->irq < 0) {
		err = ndev->irq;
		goto probe_exit_candev;
	}

	priv->ndev = ndev;
	priv->reg_xceiver = reg_xceiver;
	priv->use_hecc1int = of_property_read_bool(np, "ti,use-hecc1int");

	priv->can.bittiming_const = &ti_hecc_bittiming_const;
	priv->can.do_set_mode = ti_hecc_do_set_mode;
	priv->can.do_get_berr_counter = ti_hecc_get_berr_counter;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;

	spin_lock_init(&priv->mbx_lock);
	ndev->flags |= IFF_ECHO;
	platform_set_drvdata(pdev, ndev);
	SET_NETDEV_DEV(ndev, &pdev->dev);
	ndev->netdev_ops = &ti_hecc_netdev_ops;
	ndev->ethtool_ops = &ti_hecc_ethtool_ops;

	priv->clk = clk_get(&pdev->dev, "hecc_ck");

Annotation

Implementation Notes