一. 简介
PHY 子系统就是用于 PHY 设备相关内容的,分为 PHY 设备和 PHY 驱动,和 platform 总线一样,PHY 子系统也是一个设备、总线和驱动模型。
前面文章学习了 PHY子系统中的 PHY设备,PHY驱动,文章如下:
Linux 内核中PHY子系统(网络):PHY设备-CSDN博客
Linux 内核中PHY子系统(网络):PHY驱动-CSDN博客
本文继续学习PHY子系统中 MDIO 总线。
二. Linux 内核中PHY子系统(网络):MDIO 总线
PHY 子系统也是遵循设备、总线、驱动模型的,设备和驱动就是 phy_device 和 phy_driver。总线就是 MDIO 总线,因为 PHY 芯片是通过 MIDO 接口来管理的。
MDIO 总线最主要的工作就是匹配 PHY 设备和 PHY 驱动。在文件 drivers/net/phy/mdio_bus.c 中有如下定义:
struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.match = mdio_bus_match,
.pm = MDIO_BUS_PM_OPS,
.dev_groups = mdio_dev_groups,
};
可以看出,这里定义了一个名为“
mdio_bus_type
”的总线,这个就是
MDIO
总线,总线
的名字为“
mdio_bus
”。
2. 匹配函数: mdio_bus_match函数
重点是总线的匹配函数为 mdio_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);
}
第
6
行,采用设备树的话,先尝试使用
of_driver_match_device
来对设备和驱动进行匹配,也
就是检查
compatible
属性值与匹配表
of_match_table
里面的内容是否一致。但是对于ALPHA开发板
而言,并不是通过
of_driver_match_device
来完成
PHY
驱动和设备匹配的。
第
9
、
10
行,检查
PHY
驱动有没有提供匹配函数
match_phy_device
,如果有的话就直接调
用
PHY
驱动提供的匹配函数完成与设备的匹配。
第
12
、
13
行,如果上面两个匹配方法都无效的话就使用最后一种,
phy_driver
里面有两个成员变量
phy_id
和
phy_id_mask
,表示此驱动所匹配的
PHY
芯片
ID
以及
ID
掩码,
PHY
驱动
编写人员需要给这两个成员变量赋值。
phy_device
也有一个
phy_id
成员变量,表示此
PHY
芯
片的
ID
,
phy_device
里面的
phy_id
是在注册
PHY
设备的时候,调用
get_phy_id
函数直接读取
PHY
芯片内部
ID
寄存器得到的!
很明显
PHY
驱动和
PHY
设备中的
ID
要一样,这样才能匹配
起来。
所以最后一种方法就是对比
PHY
驱动和
PHY
设备中的
phy_id
是否一致,这里需要与
PHY
驱动里面的
phy_id_mask
进行与运算,如果结果一致的话就说明驱动和设备匹配。
如果 PHY 设备和 PHY 驱动匹配,那么就使用指定的 PHY 驱动,如果不匹配的话,就使用 Linux 内核自带的通用 PHY 驱动。