/*****************************************************************/
移植以太网部分需要注意下面几点:
1.之前说的在选择RMII和MII接口管脚配置的时候直接if(1)是不对的,根治的方法是把rmii_en赋值为1,方法有2中结构体里赋值或者函数里
2.还要注意vpif功能使用RMII的管脚,注释掉就可以了
3.RMII的时钟管脚是内部还是外部
4.启动后以太网PHY不正常解决方法如下
/*****************************************************************/
/driver/net/phy/phy_device.c
函数phy_device_create(struct mii_bus *bus,int addr, int phy_id)
这个函数创建PHY设备,设备的名字使用BUS ID和ADDR组合产生,现在基本可以断定就是
board-da850-evm.c
#define DA850_EVM_PHY_ID "0:01"
这个参数如果不对,系统启动后总是提示找不到phy
static const struct net_device_ops emac_netdev_ops = {
.ndo_open = emac_dev_open,
.....
}
---->emac_dev_open(struct net_device *ndev)///driver/net/davinci_emac.c 这个函数注册到net设备中,在打开的时候调用比如ifconfig eth0 up时
---->phy_connect(....)
{
....
d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id);/************导致失败的原因***************/
if (!d) {
pr_err("PHY %s not found\n", bus_id); //超级终端打印的信息就来自这里
return ERR_PTR(-ENODEV);
}
....
}
bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); //这个bus_id就来自#define DA850_EVM_PHY_ID "0:01"
---->bus_find_device(bus, start, (void *)name, match_name);
---->(match(dev, data) && get_device(dev)); 分析可以知道,这里就是在mido_bus_type上一次查找相同名字的phy设备,就是在
mdiobus_register(struct mii_bus *bus)里注册的,当然还可以继续向上捋看看什么时候用该注册
////****这里介绍顺藤摸瓜的方法:首先通过printk等找到提示字符串,sourceinsight搜索引用,找到打印函数,通过分析其参数,确定“向上”还是“平级”继续
搜索。前面的例子就是同级搜索,然后向下分析出和mido总线设备一次做匹配,这里有个跳跃就是mido总线设备的命名,注意bus_find_device_by_name函数
的参数&mdio_bus_type,通过这个才找到phy_device_create,然后在向上搜索。所以在分析的时候一定要注意结合参数,以参数为“指南针”。****////
mdiobus_register(struct mii_bus *bus) //至于addr是从MDIO模块alive寄存器得到的,mdio总线每个连接的phy对应1个bit
//至于地址是多少,查看原理图,在上电时由外部PHY芯片外部管脚决定
---->mdiobus_scan(struct mii_bus *bus, int addr)
---->get_phy_device(struct mii_bus *bus, int addr)
---->phy_device_create(struct mii_bus *bus,int addr, int phy_id)
通过PHY这个例子可以充分体现linux的设备驱动概念,各种总线,设备,驱动,通过注册函数联系在一起
需要使用的时候顺藤摸瓜,这个设计思想真是巧妙。
增加的内容:接着往祖坟上刨,phy_connect()中的错误来自bus_find_device_by_name(&mdio_bus_type, NULL, bus_id);其中比较mdio_bus_type和bus_id的字符串是否相等,mdio_bus_type的名字来自硬件检测物理PHY得来,多以这里重点是看bus_id何来?
在emac_dev_open(struct net_device *ndev)中来自net_device->priv->phy_id,如果这个phy_id为空着从mdio_bus_type处取得名字
if (!priv->phy_id) {
struct device *phy;
phy = bus_find_device(&mdio_bus_type, NULL, NULL, match_first_device);
if (phy)
priv->phy_id = dev_name(phy);
}
这里显然不是,否则的话前面就相等了,接着刨,net_device何来?接着刨
->davinci_emac_probe(struct platform_device *pdev)
一堆的填表最后
SET_NETDEV_DEV(ndev, &pdev->dev);
rc = register_netdev(ndev);
那么这个 platform_device *pdev哪里来的昵?注册device或者driver都有可能调用,线索到这里好像断了,暂时我还没找到,以后补上,我们从另外一个角度刨
从上往下刨。
soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID;
soc_info何许人也?查他的结构体,好有料啊,貌似掌管整个soc耶。。。device_initcall(da850_evm_config_emac);里把网络需要的操作都做了,还注册了
ret = da8xx_register_emac();-->ret = platform_device_register(&da8xx_mdio_device);
ret = platform_device_register(&da8xx_emac_device);
说了这么多就差最后一个关键soc和这个platform_device是怎么勾搭上的,下次再分析。。。。。。