以太网扫盲(四)phy驱动link up流程分析

1. 简介

在调试网口驱动的过程中发现phy芯片的驱动框架结构还有点复杂,不仔细研究的话还不好搞懂,另外百度到的资料也不够全面,这篇就总结梳理一下这方面的知识。

我们知道一个 phy 驱动的原理是非常简单的,一般流程如下:

  • 1、用轮询/中断的方式通过 mdio 总线读取 phy 芯片的状态。
  • 2、在 phy link 状态变化的情况下,正确配置 mac 的状态。(例如:根据 phy 自协商的速率 10/100/1000M 把 mac 配置成对应速率)

下面就以 stmmac 网口驱动为例,展示一下 phy 驱动整个调用过程。整个 phy 驱动的主要调用流程如下图所示:

2. phy_device

首先每个 phy 芯片会创建一个 struct phy_device 类型的设备,对应的有 struct phy_driver 类型的驱动,这两者实际上是挂载在 mdio_bus_type 总线上的。

2.1 mdiobus

mdio 总线的定义:

 
struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.dev_groups = mdio_bus_dev_groups,
.match = mdio_bus_match,
.uevent = mdio_uevent,
};

2.2 mdio device

网口驱动在初始化 probe() 时遍历 dts 的定义创建相应struct phy_device 类型的设备:

 
stmmac_dvr_probe()
`-| stmmac_mdio_register()
`-| stmmac_mdio_register()
`-| {
| new_bus = mdiobus_alloc();
| new_bus->read = &stmmac_xgmac2_mdio_read; // mdio 读写函数
| new_bus->write = &stmmac_xgmac2_mdio_write;
|
| of_mdiobus_register(new_bus, mdio_node);
`-| of_mdiobus_register_phy(mdio, child, addr);
`-| get_phy_device()
`-| get_phy_c22_id(bus, addr, &phy_id);
`-| {
| phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); // 通过 mdio 总线读取 phy 芯片 id
| phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
| }
| phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
`-| {
| mdiodev->dev.bus = &mdio_bus_type;
| mdiodev->dev.type = &mdio_bus_phy_type;
| mdiodev->bus_match = phy_bus_match;
| INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); // 这里就是 phy device 的轮询任务
| }
| of_mdiobus_phy_device_register()
`-| phy_device_register()
`-| device_add()

2.3 mdio driver

mdio bus 会根据 struct phy_device 的 phy id 和 struct phy_driver 进行 match,如果没有找到对应驱动会使用通用驱动 genphy_driver

 
static struct phy_driver genphy_driver = {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name = "Generic PHY",
.get_features = genphy_read_abilities,
.suspend = genphy_suspend,
.resume = genphy_resume,
.set_loopback = genphy_loopback,
};

以 genphy_driver 为例 struct phy_device 的注册过程如下:

 
phy_init()
`-| phy_driver_register(&genphy_driver, THIS_MODULE);
`-| {
| new_driver->mdiodrv.driver.bus = &mdio_bus_type;
| new_driver->mdiodrv.d
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值