Linux网络驱动之Fixed-Link(32)

接前一篇文章:Linux网络驱动之Fixed-Link(31)

 

本文内容参考:

linux phy fixed-link-CSDN博客

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驱动开发指南——设备树语法与编译工具——读懂这张"藏宝图"

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。

 

更多内容请看下回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝天居士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值