千兆网口 Freescale ETSEC + Marvell 88E1111 uboot Linux 驱动分析 五

来源:互联网 发布:服务器数据同步软件 编辑:程序博客网 时间:2024/06/12 18:46

8 of_platform总线上gianfar设备驱动添加,并绑定设备e0024000.ethernete0025000.ethernet

/driver/net/gianfar.c

module_init(gfar_init);

gfar_init à of_register_platform_driver(&gfar_driver)à of_register_driverà driver_registerà bus_add_driverà driver_attach

遍历整个of_platform总线,寻找与之相匹配的设备

driver_attach à __driver_attach à driver_match_device

drivermatch_table里的信息和dev_nod中的做比较,若符合就进入driverprobe,也就是gfar_probe

 

现在设备e0024000.ethernete0025000.ethernet都有了他们自己的驱动。

 

到这步,of_platform上的gianfar设备和mdio设备都有其各自的驱动,mdio总线上的phy设备和tbi-phy设备都有了其驱动程序,但是phy设备和gianfar设备之间还没有任何联系,phygianfar都没有初始化。现在要调用相应的驱动去初始化各个设备,连接gianfarphy

 

9 gianfar_probe 初始化gianfar设备,填充devpriv结构体。其中gfar_of_init会从of结构中读出priv->phy_node

  

10 phy的初始化,phygianfar的连接

/net/ipv4/ipconfig.c

late_initcall(ip_auto_config)

ip_auto_config à ic_open_devs à dev_change_flags à __dev_change_flags à __dev_open à ops->ndo_openà gfar_enet_open

 

gfar设备的打开函数中会去初始化phy,并connect to gianfar

 

u      gfar_enet_openà init_phy

static int init_phy(struct net_device *dev)

{

 

    interface =gfar_get_interface(dev);

    /*PHY连接和初始化*/

       priv->phydev =of_phy_connect(dev, priv->phy_node, &adjust_link, 0,

      

   

    /*配置TBI-PHY*/

       if (interface == PHY_INTERFACE_MODE_SGMII)

              gfar_configure_serdes(dev);

    . . . . .

       return 0;

}

u       of_phy_connect函数

priv->phy_node是从of结构中读出的phy的信息,还不是真正的phy,所以这里要在mdio_bus_type总线上再找一次匹配的phy。若找到phy_device *phy指针就不为空。

 

struct phy_device *of_phy_connect(struct net_device *dev,

                              struct device_node *phy_np,

                              void (*hndlr)(struct net_device *), u32 flags,

                              phy_interface_t iface)

{

/*mdio总线上找到和of tree上读出的phy_node相匹配的phy设备*/

       struct phy_device *phy = of_phy_find_device(phy_np);

 

       if (!phy)

              return NULL;

/*phy的初始化和phy的某些操作*/

       return phy_connect_direct(dev, phy, hndlr, flags, iface) ? NULL : phy;

}

 

u       phy_connect_direct函数

 

int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,

                     void (*handler)(struct net_device *), u32 flags,

                     phy_interface_t interface)

{

       int rc;

 

/*phy 连接和初始化*/

       rc = phy_attach_direct(dev, phydev, flags, interface);

      

       if (rc)

              return rc;

    /*挂载PHY状态改变后修改gianfar驱动寄存器的回调函数*/

       phy_prepare_link(phydev, handler);

    /*PHY的状态机开启*/

       phy_start_machine(phydev, NULL);

       if (phydev->irq > 0)

              {

                /*PHY中断的开启*/

                            phy_start_interrupts(phydev);

              }

             

       return 0;

}

 

u       phy_attach_direct函数

 

int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,

                    u32 flags, phy_interface_t interface)

{

       struct device *d = &phydev->dev;

 

       /* 如何该phy没有驱动,就使用genphy的驱动 */

       if (NULL == d->driver) {

              int err;

             

              d->driver = &genphy_driver.driver;

 

              err = d->driver->probe(d);

              if (err >= 0)

                     err = device_bind_driver(d);

 

              if (err)

                     return err;

       }

/*如果phy已经和gianfar连接返回*/

       if (phydev->attached_dev) {

              dev_err(&dev->dev, "PHY already attached/n");

              return -EBUSY;

       }

/*连接phygianfar*/

       phydev->attached_dev = dev;

 

       phydev->dev_flags = flags;

 

       phydev->interface = interface;

/*使用phy的驱动中的初始化函数去初始化phy设备。*/

       return phy_init_hw(phydev);

}

 

到这里,所有的gianfarphytbi-phy设备都已经注册,驱动已经加载,gianfarphy已经连接,并初始化完成。

原创粉丝点击