AM1808开发记录(五)

/*****************************************************************/
移植以太网部分需要注意下面几点:
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是怎么勾搭上的,下次再分析。。。。。。

你可能感兴趣的:(AM1808开发记录(五))