drivers/net/mdio/mdio-bcm-iproc.c

Source file repositories/reference/linux-study-clean/drivers/net/mdio/mdio-bcm-iproc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/mdio/mdio-bcm-iproc.c
Extension
.c
Size
4929 bytes
Lines
220
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 iproc_mdio_priv {
	struct mii_bus *mii_bus;
	void __iomem *base;
};

static inline int iproc_mdio_wait_for_idle(void __iomem *base)
{
	u32 val;
	unsigned int timeout = 1000; /* loop for 1s */

	do {
		val = readl(base + MII_CTRL_OFFSET);
		if ((val & BIT(MII_CTRL_BUSY_SHIFT)) == 0)
			return 0;

		usleep_range(1000, 2000);
	} while (timeout--);

	return -ETIMEDOUT;
}

static inline void iproc_mdio_config_clk(void __iomem *base)
{
	u32 val;

	val = (IPROC_GPHY_MDCDIV << MII_CTRL_DIV_SHIFT) |
		  BIT(MII_CTRL_PRE_SHIFT);
	writel(val, base + MII_CTRL_OFFSET);
}

static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg)
{
	struct iproc_mdio_priv *priv = bus->priv;
	u32 cmd;
	int rc;

	rc = iproc_mdio_wait_for_idle(priv->base);
	if (rc)
		return rc;

	/* Prepare the read operation */
	cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
		(reg << MII_DATA_RA_SHIFT) |
		(phy_id << MII_DATA_PA_SHIFT) |
		BIT(MII_DATA_SB_SHIFT) |
		(MII_DATA_OP_READ << MII_DATA_OP_SHIFT);

	writel(cmd, priv->base + MII_DATA_OFFSET);

	rc = iproc_mdio_wait_for_idle(priv->base);
	if (rc)
		return rc;

	cmd = readl(priv->base + MII_DATA_OFFSET) & MII_DATA_MASK;

	return cmd;
}

static int iproc_mdio_write(struct mii_bus *bus, int phy_id,
			    int reg, u16 val)
{
	struct iproc_mdio_priv *priv = bus->priv;
	u32 cmd;
	int rc;

	rc = iproc_mdio_wait_for_idle(priv->base);
	if (rc)
		return rc;

	/* Prepare the write operation */
	cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
		(reg << MII_DATA_RA_SHIFT) |
		(phy_id << MII_DATA_PA_SHIFT) |
		BIT(MII_DATA_SB_SHIFT) |
		(MII_DATA_OP_WRITE << MII_DATA_OP_SHIFT) |
		((u32)(val) & MII_DATA_MASK);

	writel(cmd, priv->base + MII_DATA_OFFSET);

	rc = iproc_mdio_wait_for_idle(priv->base);
	if (rc)
		return rc;

	return 0;
}

static int iproc_mdio_probe(struct platform_device *pdev)
{
	struct iproc_mdio_priv *priv;
	struct mii_bus *bus;

Annotation

Implementation Notes