分类: LINUX
2012-12-09 17:47:30
8 of_platform总线上gianfar设备驱动添加,并绑定设备e0024000.ethernet和e0025000.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
将driver的match_table里的信息和dev_nod中的做比较,若符合就进入driver的probe,也就是gfar_probe
现在设备e0024000.ethernet和e0025000.ethernet都有了他们自己的驱动。
到这步,of_platform上的gianfar设备和mdio设备都有其各自的驱动,mdio总线上的phy设备和tbi-phy设备都有了其驱动程序,但是phy设备和gianfar设备之间还没有任何联系,phy和gianfar都没有初始化。现在要调用相应的驱动去初始化各个设备,连接gianfar和phy。
9 gianfar_probe 初始化gianfar设备,填充dev和priv结构体。其中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;
}
/*连接phy和gianfar*/
phydev->attached_dev = dev;
phydev->dev_flags = flags;
phydev->interface = interface;
/*使用phy的驱动中的初始化函数去初始化phy设备。*/
return phy_init_hw(phydev);
}
到这里,所有的gianfar,phy,tbi-phy设备都已经注册,驱动已经加载,gianfar和phy已经连接,并初始化完成。