drivers/net/can/m_can/m_can_platform.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/m_can/m_can_platform.c
Extension
.c
Size
5787 bytes
Lines
243
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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

struct m_can_plat_priv {
	struct m_can_classdev cdev;

	void __iomem *base;
	void __iomem *mram_base;
};

static inline struct m_can_plat_priv *cdev_to_priv(struct m_can_classdev *cdev)
{
	return container_of(cdev, struct m_can_plat_priv, cdev);
}

static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
{
	struct m_can_plat_priv *priv = cdev_to_priv(cdev);

	return readl(priv->base + reg);
}

static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
{
	struct m_can_plat_priv *priv = cdev_to_priv(cdev);
	void __iomem *src = priv->mram_base + offset;

	while (val_count--) {
		*(unsigned int *)val = ioread32(src);
		val += 4;
		src += 4;
	}

	return 0;
}

static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
{
	struct m_can_plat_priv *priv = cdev_to_priv(cdev);

	writel(val, priv->base + reg);

	return 0;
}

static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
			    const void *val, size_t val_count)
{
	struct m_can_plat_priv *priv = cdev_to_priv(cdev);
	void __iomem *dst = priv->mram_base + offset;

	while (val_count--) {
		iowrite32(*(unsigned int *)val, dst);
		val += 4;
		dst += 4;
	}

	return 0;
}

static const struct m_can_ops m_can_plat_ops = {
	.read_reg = iomap_read_reg,
	.write_reg = iomap_write_reg,
	.write_fifo = iomap_write_fifo,
	.read_fifo = iomap_read_fifo,
};

static int m_can_plat_probe(struct platform_device *pdev)
{
	struct m_can_classdev *mcan_class;
	struct m_can_plat_priv *priv;
	struct resource *res;
	void __iomem *addr;
	void __iomem *mram_addr;
	struct phy *transceiver;
	int irq = 0, ret = 0;

	mcan_class = m_can_class_allocate_dev(&pdev->dev,
					      sizeof(struct m_can_plat_priv));
	if (IS_ERR(mcan_class))
		return PTR_ERR(mcan_class);

	priv = cdev_to_priv(mcan_class);

	ret = m_can_class_get_clocks(mcan_class);
	if (ret)
		goto probe_fail;

	addr = devm_platform_ioremap_resource_byname(pdev, "m_can");
	if (IS_ERR(addr)) {
		ret = PTR_ERR(addr);
		goto probe_fail;
	}

Annotation

Implementation Notes