接前一篇文章:Linux网络驱动之Fixed-Link(31)
本文内容参考:
linux phy处理流程一:探测phy设备_phy link过程-CSDN博客
linux phy处理流程三:fixed-link处理-CSDN博客
ARM与交换芯片mac_to_mac固定模式总结_mac to mac-CSDN博客
rk3399 mac to mac 连接switch - tccxy - 博客园
嵌入式Linux驱动开发 —— 从 DTS 到代码的桥梁与简单OF系列API
嵌入式Linux驱动开发指南——设备树语法与编译工具——读懂这张"藏宝图"
特此致谢!
上一回讲到了T113 SDK中的board.dts的gmac0结点信息:
&gmac0 {
phy-mode = "rgmii-id";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&gmac0_pins_default &gmac0_pins_pg11>;
pinctrl-1 = <&gmac0_pins_sleep>;
sunxi,phy-clk-type = <0>;
use_ephy25m = <1>;
tx-delay = <2>;
rx-delay = <0>;
status = "okay";
fixed-link {
speed = <1000>;
full-duplex;
};
};
本回来看Linux内核是如何解析“fixed-link”属性,并进行驱动和设备配置及加载、添加的。
dts文件经过DTC(Device Tree Compiler)的3个编译步骤:
1)词法分析(dtc-lexer.l):把文本切分成Token,识别为标识符、赋值号、字符串和分号;
2)语法分析(dtc-parser.y):根据文法规则把Token流构建成内存中的树形结构;
3)代码生成(flattree.c):遍历语法树,“拍扁”成线性的DTB二进制格式。
编译生成dtb文件,并加载进Linux内核。完整流程如下图所示:



Linux内核解析设备树相关代码及流程简述如下:
// 设备树解析核心函数调用链
start_kernel()
--> setup_arch(&command_line)
--> unflatten_device_tree()
--> __unflatten_device_tree()
--> unflatten_dt_nodes()
// 驱动匹配流程
driver_register()
--> bus_add_driver()
--> driver_attach()
--> __driver_attach()
--> driver_match_device()
--> of_driver_match_device()
// 设备创建流程
of_platform_populate()
--> of_platform_bus_create()
--> of_platform_device_create_pdata()
对于T113系列SDK,相关的处理在bsp/drivers/gmac/sunxi-gmac.c中,代码如下:
static int sunxi_gmac_hardware_init(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct sunxi_gmac *chip = netdev_priv(ndev);
struct device_node *np = pdev->dev.of_node;
int ret;
chip->phy_node = of_parse_phandle(np, "phy-handle", 0);
if (of_phy_is_fixed_link(np)) {
ret = of_phy_register_fixed_link(np);
if (ret < 0) {
netdev_info(ndev, "Failed to register fixed PHY link: %d\n",
ret);
return ret;
}
// priv->phy_node = of_node_get(np);
chip->is_fixed_link = true;
sunxi_info(chip->dev, "Registered fixed PHY link\n");
}
sunxi_info(chip->dev, "Registered fixed PHY link\n");
ret = sunxi_gmac_power_on(chip);
if (ret) {
sunxi_err(chip->dev, "Gmac power on failed\n");
ret = -EINVAL;
goto power_on_err;
}
ret = sunxi_gmac_clk_enable(chip);
if (ret) {
sunxi_err(chip->dev, "Clk enable is failed\n");
ret = -EINVAL;
goto clk_enable_err;
}
#if IS_ENABLED(CONFIG_AW_EPHY)
ret = chip->ephy_ops->hardware_init(chip);
if (ret) {
sunxi_err(chip->dev, "ephy init failed\n");
ret = -EINVAL;
goto ephy_init_err;
}
#endif /* CONFIG_AW_EPHY */
return 0;
#if IS_ENABLED(CONFIG_AW_EPHY)
ephy_init_err:
sunxi_gmac_clk_disable(chip);
#endif /* CONFIG_AW_EPHY */
clk_enable_err:
sunxi_gmac_power_off(chip);
power_on_err:
return ret;
}
重点关注其中与Fixed-Link有关的代码片段:
chip->phy_node = of_parse_phandle(np, "phy-handle", 0);
if (of_phy_is_fixed_link(np)) {
ret = of_phy_register_fixed_link(np);
if (ret < 0) {
netdev_info(ndev, "Failed to register fixed PHY link: %d\n",
ret);
return ret;
}
// priv->phy_node = of_node_get(np);
chip->is_fixed_link = true;
sunxi_info(chip->dev, "Registered fixed PHY link\n");
}
sunxi_info(chip->dev, "Registered fixed PHY link\n");
np为mac控制器设备树配置信息:
struct device_node *np = pdev->dev.of_node;
对应的就是dts文件中的gmac0结点信息:
&gmac0 {
phy-mode = "rgmii-id";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&gmac0_pins_default &gmac0_pins_pg11>;
pinctrl-1 = <&gmac0_pins_sleep>;
sunxi,phy-clk-type = <0>;
use_ephy25m = <1>;
tx-delay = <2>;
rx-delay = <0>;
status = "okay";
fixed-link {
speed = <1000>;
full-duplex;
};
};
前文书(Linux网络驱动之Fixed-Link(5)_linux fixed-link-CSDN博客)已经讲过,of_phy_is_fixed_link函数在kernel/linux-5.10-origin/drivers/net/mdio/of_mdio.c中,代码如下:
/*
* of_phy_is_fixed_link() and of_phy_register_fixed_link() must
* support two DT bindings:
* - the old DT binding, where 'fixed-link' was a property with 5
* cells encoding various informations about the fixed PHY
* - the new DT binding, where 'fixed-link' is a sub-node of the
* Ethernet device.
*/
bool of_phy_is_fixed_link(struct device_node *np)
{
struct device_node *dn;
int len, err;
const char *managed;
/* New binding */
dn = of_get_child_by_name(np, "fixed-link");
if (dn) {
of_node_put(dn);
return true;
}
err = of_property_read_string(np, "managed", &managed);
if (err == 0 && strcmp(managed, "auto") != 0)
return true;
/* Old binding */
if (of_get_property(np, "fixed-link", &len) &&
len == (5 * sizeof(__be32)))
return true;
return false;
}
EXPORT_SYMBOL(of_phy_is_fixed_link);
1)of_phy_is_fixed_link函数首先判断设备树中的设备结点中是否有"fixed-link",如果有,直接返回true;
2)否则进一步判断结点中是否有"managed"属性,如果有,则判断其值是否是"auto"。如果有"managed"但又不是"auto",则说明只能是"fixed-link",返回true;
3)如果能走下来(并未返回),则尝试旧版写法匹配。如果是按照旧版写法的格式,有fixed-link属性,且其中的值的个数为5 * 32位整数值,则同样返回true。
对于T113的board.dts来说,由于gmac0结点中就有显式的“fixed-link”属性,
&gmac0 {
phy-mode = "rgmii-id";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&gmac0_pins_default &gmac0_pins_pg11>;
pinctrl-1 = <&gmac0_pins_sleep>;
sunxi,phy-clk-type = <0>;
use_ephy25m = <1>;
tx-delay = <2>;
rx-delay = <0>;
status = "okay";
fixed-link {
speed = <1000>;
full-duplex;
};
};
因此第1个条件就满足了,从而在第1个条件处就返回了true。
更多内容请看下回。
946

被折叠的 条评论
为什么被折叠?



