phy_init
--> mdio_bus_init 注册mdio_bus_type总线。
--> phy_driver_register 注册通用phy驱动,并匹配device在这里注册的genphy_driver一般不会被特定的设备绑定。然后在绑定时调用
Driver->bus->match接口,最终调用到mdio_bus_type->mdio_bus_match。
Phy driver注册到mdio_bus_type总线流程如下:
static struct phy_driver broadcom_drivers[] = {
{
.phy_id = PHY_ID_BCM5482,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5482",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = bcm5482_config_init,
.read_status = bcm5482_read_status,
.ack_interrupt = bcm_phy_ack_intr,
.config_intr = bcm_phy_config_intr,
};
module_phy_driver(broadcom_drivers);主要通过这个宏函数接口注册phy驱动。
mdio_bus_match
--> mdio->bus_match = phy_bus_match(主要用于匹配phyID):在phy_device_create里赋值的
-->really_probe
-->drv->probe = phy_probe
Phy device注册流程如下:
- 注册mdio总线驱动,设备是通过dts创建的。
static struct platform_driver davinci_mdio_driver = {
.driver = {
.name = "davinci_mdio",
.pm = &davinci_mdio_pm_ops,
.of_match_table = of_match_ptr(davinci_mdio_of_mtable),
},
.probe = davinci_mdio_probe,
.remove = davinci_mdio_remove,
};
//初始化TI MII总线驱动
static int __init davinci_mdio_init(void)
{
return platform_driver_register(&davinci_mdio_driver);
}
device_initcall(davinci_mdio_init);
然后mdio总线设备和驱动绑定成功后调用davinci_mdio_probe函数进行总线注册的具体流程。
- 代码调用流程:
davinci_mdio_init 总线注册入口
-->davinci_mdio_probe 总线初始化入口,填充总线信息。包括总线的读写和复位函数都在此赋值。
-->of_mdiobus_register
-->mdiobus_register
-->__mdiobus_register
-->mdiobus_scan 扫描总线上挂接的phy设备
-->get_phy_device
-->get_phy_id 通过总线读取phy芯片2/3寄存器的phy ID
-->phy_device_create 创建phy设备用于匹配phy驱动
-->phy_device_register 注册phy设备并寻找总线上的phy驱动
至此,phy的device和driver在注册MDIO总线时就已经绑定好了。后续phy_driver结构体中相关的初始化函数,
是在网卡初始化的时候再调用config_init接口关联的函数进行配置的。
- Phy初始化配置函数流程:
对用的网卡驱动函数
--> phy_connect
-->phy_connect_direct
-->phy_attach_direct
-->phy_init_hw 具体配置phy芯片
-->phy_start_machine