塞外博翁 发表于 2023-11-27 22:23:20

GMAC网卡Fixed-Link模式

GMAC网卡Fixed-Link模式

GMACfixed-link固定链接模式,mac与对端的连接方式是写死的,通常用于mac to mac(不排除mac to phy的情况)。内核要支持fixed-link模式,需要打开CONFIG_FIXED_PHY配置。
社区版linux的gmac网卡platform平台驱动中,在设备树默认下支持fixed-link,gmac网卡platform平台驱动默认不支持ACPI模式。
fixed-link模式的实现,概括起来就两步,

[*]通过fixed_phy_register创建phy device
[*]连接phy device
fixed-link的link状态通常是固定的,但也可以通过gpio GPIOF_DIR_IN寄存器获取。
设备树Fixed-Link实现

以4.19.90内核版本为例其实现方式如下(内核版本5.3之后使用phylink替代了phy lib,实现接口有所不同):
设备树配置中定义fixed-link属性

http://bbs.itdo.tech/./images/1701062093815.png
设备树fixed-link配置
stmac驱动实现,of_phy_register_fixed_link函数读取设备树fixed-link属性并通过fixed_phy_register创建phy device,of_phy_connect连接phy device。
stmmac_platform.c:
static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
             struct device_node *np, struct device *dev)
{
... ...
    /* If phy-handle is not specified, check if we have a fixed-phy */
    if (!plat->phy_node && of_phy_is_fixed_link(np)) {
                if ((of_phy_register_fixed_link(np) < 0))
            return -ENODEV;

      dev_dbg(dev, "Found fixed-link subnode\n");
      plat->phy_node = of_node_get(np);
      mdio = false;
    }
... ...
}

stmmac_main.c:
static int stmmac_init_phy(struct net_device *dev)
{
... ...
        if (priv->plat->phy_node) {
                phydev = of_phy_connect(dev, priv->plat->phy_node,
                                        &stmmac_adjust_link, 0, interface);
... ...
}通过of_phy_register_fixed_link函数可知,fixed-link的配置方式不只一种。
/drivers/of/of_mdio.c:
int of_phy_register_fixed_link(struct device_node *np)
{
        struct fixed_phy_status status = {};
        struct device_node *fixed_link_node;
        u32 fixed_link_prop;
        const char *managed;
        int link_gpio = -1;

        if (of_property_read_string(np, "managed", &managed) == 0 &&
          strcmp(managed, "in-band-status") == 0) {
                /* status is zeroed, namely its .link member */
                goto register_phy;
        }

        /* New binding */
        fixed_link_node = of_get_child_by_name(np, "fixed-link");
        if (fixed_link_node) {
                status.link = 1;
                status.duplex = of_property_read_bool(fixed_link_node,
                                                      "full-duplex");
                if (of_property_read_u32(fixed_link_node, "speed",
                                       &status.speed)) {
                        of_node_put(fixed_link_node);
                        return -EINVAL;
                }
                status.pause = of_property_read_bool(fixed_link_node, "pause");
                status.asym_pause = of_property_read_bool(fixed_link_node,
                                                          "asym-pause");
                link_gpio = of_get_named_gpio_flags(fixed_link_node,
                                                  "link-gpios", 0, NULL);
                of_node_put(fixed_link_node);
                if (link_gpio == -EPROBE_DEFER)
                        return -EPROBE_DEFER;

                goto register_phy;
        }

        /* Old binding */
        if (of_property_read_u32_array(np, "fixed-link", fixed_link_prop,
                                     ARRAY_SIZE(fixed_link_prop)) == 0) {
                status.link = 1;
                status.duplex = fixed_link_prop;
                status.speed= fixed_link_prop;
                status.pause= fixed_link_prop;
                status.asym_pause = fixed_link_prop;
                goto register_phy;
        }

        return -ENODEV;

register_phy:
        return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, link_gpio,
                                                  np));
}
EXPORT_SYMBOL(of_phy_register_fixed_link);ACPI Fixed-Link实现

本质上ACPI和设备树fixed-link实现是一致的,只是部分接口函数不同,ACPI下可以使用phy_connect_direct进行连接(5.3之后的内核版本使用phylink模式,连接函数是phylink_connect_phy)。
stmmac_platform.c:
int fw_phy_register_fixed_link(struct fwnode_handle *np,
                             struct plat_stmmacenet_data *plat)
{
        struct fixed_phy_status status = {};
        u32 fixed_link_prop;
        int size = 5, err;
        int link_gpio = -1;
        struct phy_device *phydev = NULL;

        if (FORCE_FIXED_LINK) {
                status.link = 1;
                status.duplex = DUPLEX_FULL;
                status.speed = SPEED_1000;
                pr_info("force fixed-link busid %d\n", plat->bus_id);
        } else {
                err = fwnode_property_read_u32_array(np, "fixed-link", fixed_link_prop, size);
                if (err) {
                        pr_err("----there is no fixed-link property in DSD--\n");
                        return 0;
                }
                status.link = 1;
                status.duplex = fixed_link_prop;
                status.speed = fixed_link_prop;
                status.pause= fixed_link_prop;
                status.asym_pause = fixed_link_prop;
        }

        phydev = fixed_phy_register(PHY_POLL, &status, link_gpio, 0);
        if (IS_ERR(phydev)) {
                pr_err("fixed_phy_register failed\n");
                return -1;
        }
        plat->fixedphydev = phydev;
        return 0;
}

stmmac_main.c:
static int stmmac_init_phy(struct net_device *dev)
{
... ...
if (priv->plat->fixedphydev) {
                phydev = priv->plat->fixedphydev;
                if (phy_connect_direct(dev, phydev, &stmmac_adjust_link,
                                     interface)) {
                        netdev_err(priv->dev, "phy_connect_direct failed\n");
                        phydev = NULL;
}
... ...
}
来源:https://www.cnblogs.com/forwards/p/17859265.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: GMAC网卡Fixed-Link模式