drivers/net/can/flexcan/flexcan-core.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/flexcan/flexcan-core.c
Extension
.c
Size
70069 bytes
Lines
2457
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 flexcan_netdev_ops = {
	.ndo_open	= flexcan_open,
	.ndo_stop	= flexcan_close,
	.ndo_start_xmit	= flexcan_start_xmit,
};

static int register_flexcandev(struct net_device *dev)
{
	struct flexcan_priv *priv = netdev_priv(dev);
	struct flexcan_regs __iomem *regs = priv->regs;
	u32 reg, err;

	err = flexcan_clks_enable(priv);
	if (err)
		return err;

	/* select "bus clock", chip must be disabled */
	err = flexcan_chip_disable(priv);
	if (err)
		goto out_clks_disable;

	reg = priv->read(&regs->ctrl);
	if (priv->clk_src)
		reg |= FLEXCAN_CTRL_CLK_SRC;
	else
		reg &= ~FLEXCAN_CTRL_CLK_SRC;
	priv->write(reg, &regs->ctrl);

	err = flexcan_chip_enable(priv);
	if (err)
		goto out_chip_disable;

	/* set freeze, halt */
	err = flexcan_chip_freeze(priv);
	if (err)
		goto out_chip_disable;

	/* activate FIFO, restrict register access */
	reg = priv->read(&regs->mcr);
	reg |=  FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
	priv->write(reg, &regs->mcr);

	/* Currently we only support newer versions of this core
	 * featuring a RX hardware FIFO (although this driver doesn't
	 * make use of it on some cores). Older cores, found on some
	 * Coldfire derivates are not tested.
	 */
	reg = priv->read(&regs->mcr);
	if (!(reg & FLEXCAN_MCR_FEN)) {
		netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");
		err = -ENODEV;
		goto out_chip_disable;
	}

	err = register_candev(dev);
	if (err)
		goto out_chip_disable;

	/* Disable core and let pm_runtime_put() disable the clocks.
	 * If CONFIG_PM is not enabled, the clocks will stay powered.
	 */
	flexcan_chip_disable(priv);
	pm_runtime_put(priv->dev);

	return 0;

 out_chip_disable:
	flexcan_chip_disable(priv);
 out_clks_disable:
	flexcan_clks_disable(priv);
	return err;
}

static void unregister_flexcandev(struct net_device *dev)
{
	unregister_candev(dev);
}

static int flexcan_setup_stop_mode_gpr(struct platform_device *pdev)
{
	struct net_device *dev = platform_get_drvdata(pdev);
	struct device_node *np = pdev->dev.of_node;
	struct device_node *gpr_np;
	struct flexcan_priv *priv;
	phandle phandle;
	u32 out_val[3];
	int ret;

	if (!np)
		return -EINVAL;

Annotation

Implementation Notes