linux Phy 设备驱动

MDIO/MII 介绍

MII是Medium Independent Interface的缩写,是一种标准接口,该接口主要应用于MAC层和PHY层之间的以太网数据传输。

MII接口的类型有很多,常用的有MII、RMII、SMII、SSMII、SSSMII、GMII、RGMII、SGMII、TBI、RTBI、XGMII、XAUI、XLAUI等。

MDIO是Management Data Input/Output的缩写,是一种串行通信总线,类似于I2C,该总线由IEEE通过以太网标准IEEE 802.3的若干条款加以定义,一般用于微控制器或是mac控制器与phy相连接。MDIO必须于MDC一起使用,MDC是作为MDIO的时钟信号。

MDIO是属于MII接口的一部分。

解析phy驱动:

驱动流程:

phy_driver_regitster -->driver_register-->bus_add_driver-->driver_attach-->bus_for_each_dev-->__driver_attach(通过bus_for_each_dev参数回调)-->driver_probe_device(drv, dev)-->really_probe(dev, drv)-->drv->probe(dev).
int phy_driver_register(struct phy_driver *new_driver)
{
	int retval;
	new_driver->driver.name = new_driver->name;
	new_driver->driver.bus = &mdio_bus_type;
	new_driver->driver.probe = phy_probe;
	new_driver->driver.remove = phy_remove;
	retval = driver_register(&new_driver->driver);
	if (retval) {
		pr_err("%s: Error %d in registering driver\n",
		       new_driver->name, retval);
		return retval;
	}
	pr_debug("%s: Registered new driver\n", new_driver->name);
	return 0;
}

可见phy的driver是挂载在mdio_bus上的。
driver_register(struct device_driver *drv):检测mdio_bus_type上是否已经注册该设备了。
bus_add_driver(struct device_driver *drv):Add a driver to the bus.
driver_attach(struct device_driver *drv):让总线上的设备与驱动匹配.
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach): 回调函数__driver_attach.
 __driver_attach(struct device *dev, void *data):
    if (!driver_match_device(drv, dev))
return 0;
driver_match_device(drv, dev)就是匹配driver 与 device。

static inline int driver_match_device(struct device_driver *drv,
                      struct device *dev)
{
    return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
drv->bus->match 匹配函数 源码:
static int mdio_bus_match(struct device *dev, struct device_driver *drv)
{
    struct phy_device *phydev = to_phy_device(dev);
    struct phy_driver *phydrv = to_phy_driver(drv);


    if (of_driver_match_device(dev, drv))
        return 1;

    if (phydrv->match_phy_device)
        return phydrv->match_phy_device(phydev);

    return ((phydrv->phy_id & phydrv->phy_id_mask) ==
            (phydev->phy_id & phydrv->phy_id_mask));
}


可以确定匹配是通过driver和device的phy_id & phy_id_mask, 而不是通过设备于驱动名字匹配。

driver_probe_device(drv, dev):从这里追踪代码可以找到really_probe(dev, drv),继续追踪drv->probe(dev),到此结束

你可能感兴趣的:(linux,操作系统,phy驱动,交换机驱动)