linux Phy 设备驱动
MII/MDIOMII是Medium Independent Interface的缩写,是一种标准接口,该接口主要应用于MAC层和PHY层之间的以太网数据传输。MII接口的类型有很多,常用的有MII、RMII、SMII、SSMII、SSSMII、GMII、RGMII、SGMII、TBI、RTBI、XGMII、XAUI、XLAUI等。MDIO是Management Data Input/
·
MDIO/MII 介绍
可见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 匹配函数 源码:
可以确定匹配是通过driver和device的phy_id & phy_id_mask, 而不是通过设备于驱动名字匹配。
driver_probe_device(drv, dev):从这里追踪代码可以找到really_probe(dev, drv),继续追踪drv->probe(dev),到此结束
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),到此结束
更多推荐
已为社区贡献1条内容
所有评论(0)