Fixed phy是PHYLIB的feature之一,在后续的kernel版本中 PHYLIB和FIXED_PHY被PHYLINK所取代(参考phylink — The Linux Kernel documentation)。FIXED-PHY的本质和externel phy没有区别,只是使用虚拟的mii_bus来注册fixed phy,仍然需要创建phydev, 仍然需要phy driver,如果没有注册specific driver则是默认使用generic phy driver. 并且需要利用phydev的状态机的运转来adjust link。而后续引入的PHYLINK则是大大的优化了fixed link的实现以及对SFP的支持(这里暂不讨论)。
fixed phy的DTS配置通常如下, 在创建netdev的mac节点中使用子节点“fixed-link”来表示。“在后续PHYLINK中仍然使用“fixed-link”子节点表示 fixed link。
mac0 {
......
phy-mode = "sgmii"
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
Fixed phy的注册和connect参考kernel of_phy_get_and_connect函数。可以在probe driver中参考该函数实现
struct phy_device *of_phy_get_and_connect(struct net_device *dev,
struct device_node *np,
void (*hndlr)(struct net_device *))
{
phy_interface_t iface;
struct device_node *phy_np;
struct phy_device *phy;
int ret;
ret = of_get_phy_mode(np, &iface);
if (ret)
return NULL;
if (of_phy_is_fixed_link(np)) {
ret = of_phy_register_fixed_link(np);
if (ret < 0) {
netdev_err(dev, "broken fixed-link specification\n");
return NULL;
}
phy_np = of_node_get(np);
} else {
phy_np = of_parse_phandle(np, "phy-handle", 0);
if (!phy_np)
return NULL;
}
phy = of_phy_connect(dev, phy_np, hndlr, 0, iface);
of_node_put(phy_np);
return phy;
}
EXPORT_SYMBOL(of_phy_get_and_connect);
np为创建netdev的dts节点的device node(这里是mac0), of_phy_register_fixed_link会为fixed phy创建phydev, 注意该函数传入的参数np为mac0的device node。 在__fixed_phy_register中会将该device node保存给fixed phy的phydev: phy->mdio.dev.of_node = np. 即fixed phy的phydev与mac0的device node绑定。这样后面of_phy_connect对fixed phy传入的np就会通过该np找到fixed phy的phydev。 而对于普通的external phy而言, phydev的创建和注册在mdio driver中, 而mac0节点中使用“phy-handle”引用mdio中的phy节点。