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

本文详细介绍了如何在平台总线上为Gianfar设备添加驱动,并将其与两个Ethernet设备e0024000.ethernet和e0025000.ethernet绑定。随后,通过调用相应的驱动程序初始化设备,实现Gianfar设备与PHY设备之间的连接与初始化。重点阐述了Gianfar设备的打开函数中如何初始化PHY设备,并通过调用of_phy_connect函数在MDIO总线上查找与oftree上读出的PHY节点匹配的PHY设备,最后完成连接和初始化。

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的初始化,phy gianfar的连接

/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已经连接,并初始化完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值