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),到此結束
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章