1. MDIO驱动匹配流程概述
在Linux网络子系统中,MDIO(Management Data Input/Output)总线扮演着PHY设备管理的核心角色。驱动匹配流程是确保硬件PHY设备与对应驱动程序正确关联的关键机制。这个过程类似于酒店入住系统——当新客人(PHY设备)到达时,前台(MDIO子系统)需要根据客人特征(PHY ID)找到最合适的服务人员(驱动程序)来接待。
整个匹配流程包含三个主要阶段:
- 设备注册与总线扫描:发现总线上连接的PHY设备
- 驱动匹配:将设备与合适的驱动程序关联
- Probe过程:完成设备特定的初始化工作
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 设备注册与总线扫描机制
2.1 MDIO总线初始化
MDIO总线控制器的初始化是整个流程的起点。当内核加载MDIO总线控制器驱动时,会执行以下关键操作:
- 创建mii_bus实例:这是MDIO总线的软件抽象
- 硬件资源初始化:配置控制器寄存器、时钟等
- 注册总线:调用mdiobus_register函数将总线添加到系统
c复制struct mii_bus *mdio_bus_alloc(void)
{
struct mii_bus *bus;
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (!bus)
return NULL;
bus->read = &mdiobus_read;
bus->write = &mdiobus_write;
bus->reset = &mdiobus_reset;
// 其他操作初始化
return bus;
}
2.2 总线扫描过程
mdiobus_scan函数是探测PHY设备的核心,其工作流程如下:
- 地址遍历:扫描0-31的所有可能PHY地址
- PHY ID读取:通过MDIO读取每个地址的PHYID寄存器
- 有效性验证:检查读取值是否为有效PHY ID
- 设备创建:为有效PHY创建phy_device实例
- 设备注册:将phy_device注册到MDIO总线
注意:全0或全1的PHY ID通常表示该地址没有设备,扫描时会跳过这些地址
c复制int mdiobus_scan(struct mii_bus *bus, int addr)
{
struct phy_device *phydev;
int err;
phydev = get_phy_device(bus, addr, false);
if (IS_ERR(phydev))
return PTR_ERR(phydev);
err = phy_device_register(phydev);
if (err) {
phy_device_free(phydev);
return err;
}
bus->phy_map[addr] = phydev;
return 0;
}
2.3 设备树静态配置
除了动态扫描,Linux还支持通过设备树静态配置PHY设备。设备树中的典型MDIO节点配置如下:
code复制mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
max-speed = <1000>;
reset-gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
reset-assert-us = <10000>;
};
};
静态配置的优势包括:
- 避免自动扫描的不确定性
- 支持更精确的设备参数配置
- 允许提前指定PHY地址和特性
- 支持GPIO复位等高级功能
3. 驱动匹配机制详解
3.1 匹配流程实现
MDIO驱动匹配由mdio_bus_match函数实现,遵循Linux设备模型标准。匹配过程的核心是比较PHY标识符:
- 提取设备phy_id:来自硬件PHYID寄存器
- 应用驱动掩码:phy_id & phy_id_mask
- 比较标识符:结果与驱动的phy_id比较
- 执行probe:匹配成功后调用驱动的probe方法
c复制
