drivers/net/mdio/mdio-mux-bcm6368.c

Source file repositories/reference/linux-study-clean/drivers/net/mdio/mdio-mux-bcm6368.c

File Facts

System
Linux kernel
Corpus path
drivers/net/mdio/mdio-mux-bcm6368.c
Extension
.c
Size
4194 bytes
Lines
183
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 bcm6368_mdiomux_desc {
	void *mux_handle;
	void __iomem *base;
	struct device *dev;
	struct mii_bus *mii_bus;
	int ext_phy;
};

static int bcm6368_mdiomux_read(struct mii_bus *bus, int phy_id, int loc)
{
	struct bcm6368_mdiomux_desc *md = bus->priv;
	uint32_t reg;
	int ret;

	__raw_writel(0, md->base + MDIOC_REG);

	reg = MDIOC_RD_MASK |
	      (phy_id << MDIOC_PHYID_SHIFT) |
	      (loc << MDIOC_REG_SHIFT);
	if (md->ext_phy)
		reg |= MDIOC_EXT_MASK;

	__raw_writel(reg, md->base + MDIOC_REG);
	udelay(50);
	ret = __raw_readw(md->base + MDIOD_REG);

	return ret;
}

static int bcm6368_mdiomux_write(struct mii_bus *bus, int phy_id, int loc,
				 uint16_t val)
{
	struct bcm6368_mdiomux_desc *md = bus->priv;
	uint32_t reg;

	__raw_writel(0, md->base + MDIOC_REG);

	reg = MDIOC_WR_MASK |
	      (phy_id << MDIOC_PHYID_SHIFT) |
	      (loc << MDIOC_REG_SHIFT);
	if (md->ext_phy)
		reg |= MDIOC_EXT_MASK;
	reg |= val;

	__raw_writel(reg, md->base + MDIOC_REG);
	udelay(50);

	return 0;
}

static int bcm6368_mdiomux_switch_fn(int current_child, int desired_child,
				     void *data)
{
	struct bcm6368_mdiomux_desc *md = data;

	md->ext_phy = desired_child;

	return 0;
}

static int bcm6368_mdiomux_probe(struct platform_device *pdev)
{
	struct bcm6368_mdiomux_desc *md;
	struct mii_bus *bus;
	struct resource *res;
	int rc;

	md = devm_kzalloc(&pdev->dev, sizeof(*md), GFP_KERNEL);
	if (!md)
		return -ENOMEM;
	md->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -EINVAL;

	/*
	 * Just ioremap, as this MDIO block is usually integrated into an
	 * Ethernet MAC controller register range
	 */
	md->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
	if (!md->base) {
		dev_err(&pdev->dev, "failed to ioremap register\n");
		return -ENOMEM;
	}

	md->mii_bus = devm_mdiobus_alloc(&pdev->dev);
	if (!md->mii_bus) {
		dev_err(&pdev->dev, "mdiomux bus alloc failed\n");
		return -ENOMEM;

Annotation

Implementation Notes