drivers/net/can/bxcan.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/bxcan.c
Extension
.c
Size
27756 bytes
Lines
1102
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 bxcan_netdev_ops = {
	.ndo_open = bxcan_open,
	.ndo_stop = bxcan_stop,
	.ndo_start_xmit = bxcan_start_xmit,
};

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

static int bxcan_do_set_mode(struct net_device *ndev, enum can_mode mode)
{
	int err;

	switch (mode) {
	case CAN_MODE_START:
		err = bxcan_chip_start(ndev);
		if (err)
			return err;

		netif_wake_queue(ndev);
		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int bxcan_get_berr_counter(const struct net_device *ndev,
				  struct can_berr_counter *bec)
{
	struct bxcan_priv *priv = netdev_priv(ndev);
	struct bxcan_regs __iomem *regs = priv->regs;
	u32 esr;
	int err;

	err = clk_prepare_enable(priv->clk);
	if (err)
		return err;

	esr = readl(&regs->esr);
	bec->txerr = FIELD_GET(BXCAN_ESR_TEC_MASK, esr);
	bec->rxerr = FIELD_GET(BXCAN_ESR_REC_MASK, esr);
	clk_disable_unprepare(priv->clk);
	return 0;
}

static int bxcan_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device *dev = &pdev->dev;
	struct net_device *ndev;
	struct bxcan_priv *priv;
	struct clk *clk = NULL;
	void __iomem *regs;
	struct regmap *gcan;
	enum bxcan_cfg cfg;
	int err, rx_irq, tx_irq, sce_irq;

	regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(regs)) {
		dev_err(dev, "failed to get base address\n");
		return PTR_ERR(regs);
	}

	gcan = syscon_regmap_lookup_by_phandle(np, "st,gcan");
	if (IS_ERR(gcan)) {
		dev_err(dev, "failed to get shared memory base address\n");
		return PTR_ERR(gcan);
	}

	if (of_property_read_bool(np, "st,can-primary"))
		cfg = BXCAN_CFG_DUAL_PRIMARY;
	else if (of_property_read_bool(np, "st,can-secondary"))
		cfg = BXCAN_CFG_DUAL_SECONDARY;
	else
		cfg = BXCAN_CFG_SINGLE;

	clk = devm_clk_get(dev, NULL);
	if (IS_ERR(clk)) {
		dev_err(dev, "failed to get clock\n");
		return PTR_ERR(clk);
	}

	rx_irq = platform_get_irq_byname(pdev, "rx0");
	if (rx_irq < 0)
		return rx_irq;

Annotation

Implementation Notes