翼度科技»论坛 云主机 LINUX 查看内容

GMAC网卡Fixed-Link模式

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
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属性


设备树fixed-link配置
stmac驱动实现,of_phy_register_fixed_link函数读取设备树fixed-link属性并通过fixed_phy_register创建phy device,of_phy_connect连接phy device。
  1. stmmac_platform.c:
  2. static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
  3.              struct device_node *np, struct device *dev)
  4. {
  5. ... ...
  6.     /* If phy-handle is not specified, check if we have a fixed-phy */
  7.     if (!plat->phy_node && of_phy_is_fixed_link(np)) {
  8.                 if ((of_phy_register_fixed_link(np) < 0))
  9.             return -ENODEV;
  10.         dev_dbg(dev, "Found fixed-link subnode\n");
  11.         plat->phy_node = of_node_get(np);
  12.         mdio = false;
  13.     }
  14. ... ...
  15. }
  16. stmmac_main.c:
  17. static int stmmac_init_phy(struct net_device *dev)
  18. {
  19. ... ...
  20.         if (priv->plat->phy_node) {
  21.                 phydev = of_phy_connect(dev, priv->plat->phy_node,
  22.                                         &stmmac_adjust_link, 0, interface);
  23. ... ...
  24. }
复制代码
通过of_phy_register_fixed_link函数可知,fixed-link的配置方式不只一种
  1. /drivers/of/of_mdio.c:
  2. int of_phy_register_fixed_link(struct device_node *np)
  3. {
  4.         struct fixed_phy_status status = {};
  5.         struct device_node *fixed_link_node;
  6.         u32 fixed_link_prop[5];
  7.         const char *managed;
  8.         int link_gpio = -1;
  9.         if (of_property_read_string(np, "managed", &managed) == 0 &&
  10.             strcmp(managed, "in-band-status") == 0) {
  11.                 /* status is zeroed, namely its .link member */
  12.                 goto register_phy;
  13.         }
  14.         /* New binding */
  15.         fixed_link_node = of_get_child_by_name(np, "fixed-link");
  16.         if (fixed_link_node) {
  17.                 status.link = 1;
  18.                 status.duplex = of_property_read_bool(fixed_link_node,
  19.                                                       "full-duplex");
  20.                 if (of_property_read_u32(fixed_link_node, "speed",
  21.                                          &status.speed)) {
  22.                         of_node_put(fixed_link_node);
  23.                         return -EINVAL;
  24.                 }
  25.                 status.pause = of_property_read_bool(fixed_link_node, "pause");
  26.                 status.asym_pause = of_property_read_bool(fixed_link_node,
  27.                                                           "asym-pause");
  28.                 link_gpio = of_get_named_gpio_flags(fixed_link_node,
  29.                                                     "link-gpios", 0, NULL);
  30.                 of_node_put(fixed_link_node);
  31.                 if (link_gpio == -EPROBE_DEFER)
  32.                         return -EPROBE_DEFER;
  33.                 goto register_phy;
  34.         }
  35.         /* Old binding */
  36.         if (of_property_read_u32_array(np, "fixed-link", fixed_link_prop,
  37.                                        ARRAY_SIZE(fixed_link_prop)) == 0) {
  38.                 status.link = 1;
  39.                 status.duplex = fixed_link_prop[1];
  40.                 status.speed  = fixed_link_prop[2];
  41.                 status.pause  = fixed_link_prop[3];
  42.                 status.asym_pause = fixed_link_prop[4];
  43.                 goto register_phy;
  44.         }
  45.         return -ENODEV;
  46. register_phy:
  47.         return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, link_gpio,
  48.                                                   np));
  49. }
  50. EXPORT_SYMBOL(of_phy_register_fixed_link);
复制代码
  ACPI Fixed-Link实现

本质上ACPI和设备树fixed-link实现是一致的,只是部分接口函数不同,ACPI下可以使用phy_connect_direct进行连接(5.3之后的内核版本使用phylink模式,连接函数是phylink_connect_phy)。
  1. stmmac_platform.c:
  2. int fw_phy_register_fixed_link(struct fwnode_handle *np,
  3.                                struct plat_stmmacenet_data *plat)
  4. {
  5.         struct fixed_phy_status status = {};
  6.         u32 fixed_link_prop[5];
  7.         int size = 5, err;
  8.         int link_gpio = -1;
  9.         struct phy_device *phydev = NULL;
  10.         if (FORCE_FIXED_LINK) {
  11.                 status.link = 1;
  12.                 status.duplex = DUPLEX_FULL;
  13.                 status.speed = SPEED_1000;
  14.                 pr_info("force fixed-link busid %d\n", plat->bus_id);
  15.         } else {
  16.                 err = fwnode_property_read_u32_array(np, "fixed-link", fixed_link_prop, size);
  17.                 if (err) {
  18.                         pr_err("----there is no fixed-link property in DSD--\n");
  19.                         return 0;
  20.                 }
  21.                 status.link = 1;
  22.                 status.duplex = fixed_link_prop[1];
  23.                 status.speed = fixed_link_prop[2];
  24.                 status.pause  = fixed_link_prop[3];
  25.                 status.asym_pause = fixed_link_prop[4];
  26.         }
  27.         phydev = fixed_phy_register(PHY_POLL, &status, link_gpio, 0);
  28.         if (IS_ERR(phydev)) {
  29.                 pr_err("fixed_phy_register failed\n");
  30.                 return -1;
  31.         }
  32.         plat->fixedphydev = phydev;
  33.         return 0;
  34. }
  35. stmmac_main.c:
  36. static int stmmac_init_phy(struct net_device *dev)
  37. {
  38. ... ...
  39. if (priv->plat->fixedphydev) {
  40.                 phydev = priv->plat->fixedphydev;
  41.                 if (phy_connect_direct(dev, phydev, &stmmac_adjust_link,
  42.                                        interface)) {
  43.                         netdev_err(priv->dev, "phy_connect_direct failed\n");
  44.                         phydev = NULL;
  45. }
  46. ... ...
  47. }
复制代码
来源:https://www.cnblogs.com/forwards/p/17859265.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具