Linux内核PHY中断调试

来源:互联网 发布:网络114推广 编辑:程序博客网 时间:2024/05/30 20:09

        Linux内核PHY中断调试       

        分类:            UBOOTLinux驱动Linux 内核和文件系统PowerPC体系结构2010-11-01 20:492098人阅读评论(5)收藏举报

今天解决了一个PHY中断的问题,现在越来越觉得我以前的想法是错误的。以前总是认为解决问题最好的办法就是看代码,从代码出发。现在发现,其实脱离代码的分析问题能力是非常重要的,代码不熟可以通过短时间的强化变熟,而分析问题的能力却需要长期的锻炼。以后再遇到困难要多想想,分析好了再去做。

问题是这样的,平台还是前几篇博客里写的:Freescale的ETSEC加Marvell的88E1111,前段时间调网络时把PHY的中断调好,插拔网线,速率双工有改变时,都会有中断产生,并响应中断。调好后以为OK了,没想到前几天出现了一个问题:Linux内核启动时,如果插着网线,PHY的中断就是好的;如果内核启动时没有插网线,PHY就没有中断,插拔网线一点反应都没有。

我开始以为是Linux内核初始化时没有注册PHY的中断,查看了内核代码和/proc/interrupt文件后发现不管网线插没插上,都会在内核中注册PHY INTERRUPT。接着,我又很盲目的在内核的/driver/net/gianfar.c, /driver/net/phy/of_mdio.c,  /driver/net/phy/Phy.c, /driver/net/phy/phy_device.c等有关MAC和PHY总线注册,设备,驱动添加,绑定,初始化的地方加了大量的打印,结果依然无从下手。

后来仔细想了一下,PHY的中断信号是接在CPU的外部中断上的,我可以先量一下插拔网线时PHY有无中断信号发出,若有,那就是MAC侧的问题,CPU没有响应中断;若没有就是PHY的问题,可能是PHY的某些配置有误。

找来示波器量了一下,果然在不插网线启动内核后,PHY的中断信号根本就没有发出来。

这样,问题的区域就去掉了很大的一块,只需要安心的查PHY侧的配置就可以了。88E1111有两个跟中断有关的寄存器,0x12和0x13,分别是使能寄存器和状态寄存器。从uboot及内核的PHY初始化代码可以看出,0x12号寄存器配置为0x6400的时候就可以使能PHY中断,中断的状态可以从读清的0x13号寄存器看出。

在uboot下使用mii read和mii write命令试了一下,并用示波器量了,在0x12号寄存器设置为0x6400,0x13号寄存器读清后插拔网线,会有中断信号的发出。由于在内核中没有类似的MII命令,所以我在网口初始化的最后打印了这两个寄存器的值,发现这两个寄存器的确是0x6400和0x0,但插拔网线却没有任何中断信号发出。

似乎是又遇到了难题,为什么同样的配置在uboot下可以,在内核下却不行呢?难道是在我打印寄存器值的后面内核代码又修改了这两个寄存器。内核下没有mii read和mii write命令实在是太不方便了,我决定用驱动来模拟这两个命令。

花了一个上午的时间,做了一个字符设备/dev/phy,并写了应用代码模拟mii read和mii write。这样我也可以在内核中实时的读到和写入PHY的寄存器了。

在驱动运行后,我迫不及待的读了几个经常用到的phy寄存器,发现了控制PHY page的寄存器0x161。这表明PHY当前在fiber侧,并不在copper。等我将PHY变回copper侧后,再读0x12寄存器,就不是0x6400了,而是0x0,中断根本没有使能。在将copper侧的0x12寄存器写入0x6400后,PHY中断终于出现了。

现在问题已经明朗了,在内核初始化时,某个地方会根据copper的连接情况修改PHYpage,若未插网线时,PHY处于fiber侧,这时候再去配置0x12号寄存器,就配到了fiber侧,并不是我们想要的结果,而真正起作用的copper侧并没有使能中断。

接下来的事情就是找到这个修改PHY page的地方,在内核中查找了一会,在/driver/net/phy/marvell.c的88E1111的初始化的地方,有这几句:

/* Enable Fiber/Copper auto selection */

temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);

temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;

phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);

这几句是使能88E11110x1b号寄存器的auto-select位,在uboot下做个实验发现,该位使能后,再重启phy0x0号寄存器的最高位),PHYpage会根据网线的插拔情况做选择,网线插上时在copper侧,网线断开时在fiber侧。这样可以断定是这里改变了PHYpage,将这三句屏蔽后,运行新内核,就不会再出现前面所说的情况了。

内核这里为什么要使能这个auto-select位呢?我目前还不知道,经过测试,这三句屏蔽对几个网口并没有什么“副作用”。如果有,我会及时的写出来。

这个问题的解决我觉得关键点是PHY中断信号的测量和内核中读写PHY的驱动的制作,一个反应了分析问题的重要性,一个反应了工欲善其事必先利其器。嵌入式的道路很漫长,以后会在这两个方面多加努力的。