drivers/net/phy/xilinx_gmii2rgmii.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/xilinx_gmii2rgmii.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/xilinx_gmii2rgmii.c
Extension
.c
Size
3713 bytes
Lines
150
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 gmii2rgmii {
	struct phy_device *phy_dev;
	const struct phy_driver *phy_drv;
	struct phy_driver conv_phy_drv;
	struct mdio_device *mdio;
};

static void xgmiitorgmii_configure(struct gmii2rgmii *priv, int speed)
{
	struct mii_bus *bus = priv->mdio->bus;
	int addr = priv->mdio->addr;
	u16 val;

	val = mdiobus_read(bus, addr, XILINX_GMII2RGMII_REG);
	val &= ~XILINX_GMII2RGMII_SPEED_MASK;

	if (speed == SPEED_1000)
		val |= BMCR_SPEED1000;
	else if (speed == SPEED_100)
		val |= BMCR_SPEED100;
	else
		val |= BMCR_SPEED10;

	mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
}

static int xgmiitorgmii_read_status(struct phy_device *phydev)
{
	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
	int err;

	if (priv->phy_drv->read_status)
		err = priv->phy_drv->read_status(phydev);
	else
		err = genphy_read_status(phydev);
	if (err < 0)
		return err;

	xgmiitorgmii_configure(priv, phydev->speed);

	return 0;
}

static int xgmiitorgmii_set_loopback(struct phy_device *phydev, bool enable,
				     int speed)
{
	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
	int err;

	if (priv->phy_drv->set_loopback)
		err = priv->phy_drv->set_loopback(phydev, enable, speed);
	else
		err = genphy_loopback(phydev, enable, speed);
	if (err < 0)
		return err;

	xgmiitorgmii_configure(priv, phydev->speed);

	return 0;
}

static int xgmiitorgmii_probe(struct mdio_device *mdiodev)
{
	struct device *dev = &mdiodev->dev;
	struct device_node *np = dev->of_node, *phy_node;
	struct gmii2rgmii *priv;
	struct clk *clkin;

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

	clkin = devm_clk_get_optional_enabled(dev, NULL);
	if (IS_ERR(clkin))
		return dev_err_probe(dev, PTR_ERR(clkin),
					"Failed to get and enable clock from Device Tree\n");

	phy_node = of_parse_phandle(np, "phy-handle", 0);
	if (!phy_node) {
		dev_err(dev, "Couldn't parse phy-handle\n");
		return -ENODEV;
	}

	priv->phy_dev = of_phy_find_device(phy_node);
	of_node_put(phy_node);
	if (!priv->phy_dev) {
		dev_info(dev, "Couldn't find phydev\n");
		return -EPROBE_DEFER;
	}

Annotation

Implementation Notes