drivers/net/mdio/mdio-mux-meson-gxl.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/mdio/mdio-mux-meson-gxl.c
Extension
.c
Size
4120 bytes
Lines
164
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 gxl_mdio_mux {
	void __iomem *regs;
	void *mux_handle;
};

static void gxl_enable_internal_mdio(struct gxl_mdio_mux *priv)
{
	u32 val;

	/* Setup the internal phy */
	val = (REG3_ENH |
	       FIELD_PREP(REG3_CFGMODE, 0x7) |
	       REG3_AUTOMDIX |
	       FIELD_PREP(REG3_PHYADDR, 8) |
	       REG3_LEDPOL |
	       REG3_PHYMDI |
	       REG3_CLKINEN |
	       REG3_PHYIP);

	writel(REG4_PWRUPRSTSIG, priv->regs + ETH_REG4);
	writel(val, priv->regs + ETH_REG3);
	mdelay(10);

	/* NOTE: The HW kept the phy id configurable at runtime.
	 * The id below is arbitrary. It is the one used in the vendor code.
	 * The only constraint is that it must match the one in
	 * drivers/net/phy/meson-gxl.c to properly match the PHY.
	 */
	writel(REG2_REVERSED | FIELD_PREP(REG2_PHYID, EPHY_GXL_ID),
	       priv->regs + ETH_REG2);

	/* Enable the internal phy */
	val |= REG3_PHYEN;
	writel(val, priv->regs + ETH_REG3);
	writel(0, priv->regs + ETH_REG4);

	/* The phy needs a bit of time to power up */
	mdelay(10);
}

static void gxl_enable_external_mdio(struct gxl_mdio_mux *priv)
{
	/* Reset the mdio bus mux to the external phy */
	writel(0, priv->regs + ETH_REG3);
}

static int gxl_mdio_switch_fn(int current_child, int desired_child,
			      void *data)
{
	struct gxl_mdio_mux *priv = dev_get_drvdata(data);

	if (current_child == desired_child)
		return 0;

	switch (desired_child) {
	case MESON_GXL_MDIO_EXTERNAL_ID:
		gxl_enable_external_mdio(priv);
		break;
	case MESON_GXL_MDIO_INTERNAL_ID:
		gxl_enable_internal_mdio(priv);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static const struct of_device_id gxl_mdio_mux_match[] = {
	{ .compatible = "amlogic,gxl-mdio-mux", },
	{},
};
MODULE_DEVICE_TABLE(of, gxl_mdio_mux_match);

static int gxl_mdio_mux_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct gxl_mdio_mux *priv;
	struct clk *rclk;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	platform_set_drvdata(pdev, priv);

	priv->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(priv->regs))
		return PTR_ERR(priv->regs);

Annotation

Implementation Notes