终于松了口气,说说这周我调试Sate210 android下DM9000 驱动的吐槽经历

 

// Topic:终于松了口气,说说这周我调试Sate210 android下DM9000 驱动的吐槽经历

//作者:gooogleman

//版权:gooogleman

//发布日期:2012.05.05 23:00

//最后修改:2012.05.06 19:00

// 原文地址:http://blog.csdn.net/gooogleman/article/details/7538560

//注意事项:商业网站未经作者同意不能转载,并且不能删除文章的任何部分,否则追究责任!

//-------------------------------------------------------------------------------------------------

    



     终于摸着门道了,先贴点资料,等下再整理。

       嘿嘿,昨晚Sate210 DM9000 网卡终于可以上网了,我一直开着Sate210 ,连续上网,看电影不停的在线播放在线视频,经过一天一夜,工作表现还是良好,我终于放心了。这次我比较happy,经过这次的调试移植,感觉自己从wince转型android开发问题不会太大了,三个月后我有信心可以更上一层楼,现在我的研发激情和刚毕业的那阵子差不了多少,现在认识那么多人,这么多android前辈指导我,我想我应该进步会更快一点。

       四月中旬,接到一个客户需求,需要帮他在Sate210 上调试好android的wifi,于是我就安排android工程师去做这个事情。因为这个S5pv210 的marvell8787 wifi模块我们已经做过成熟的产品,所以花了一天左右的时间就移植到Sate210 上去了。不过客户的需求总是在变,过了一周客户说他要改成用DM9000 了,wifi要当做备选,我也满口的答应了,因为我的Sate210 wince6.0 下的DM9000 驱动 早就工作很稳定的,我曾经连续一周不关机,网络依然使用正常,所以我觉得在android下只是一个小case ,对一个合格的android工程师来说一点困难都不会有。但是幸运的事情总是很少发生在我身上,我们android工程师调试了一周,也搞不定,他开始还反问我wince驱动是否真的正常工作?为什么这个网卡int 引脚老是高电平的?!导致我们Sate210 用作网卡中断的XEINT0 在不停的中断,一旦插入网线Sate210 就死机了。后来android工程师折腾的实在也没有方向了,就暂时放下这个android DM9000 驱动,去搞Sate210 android4.0 移植了,再后来很快到了5.1 劳动节,android驱动工程师家里有事情,就请假一周回老家去了,但是5.1 的时候客户给我电话,问我这个android2.3 下的dm9000 是否搞好了,我给他说了目前的情况,这位老兄也比较理解,只是催我尽快搞,他要做底板PCB了。我着急啊,于是我这个android菜鸟决定自己看看,抱着试试的态度去解决这个android dm9000 驱动问题。

      首先比较了三星官方开发板的dm9000 驱动和我sate210 驱动比较,发现一个字符都没有差异,看来这个都是开源的好处,到处都有代码可用。

      然后再看kernel_v210\arch\arm\plat-s5p  下的devs.c文件,发现还是用官方电路图的XEINT9

/* DM9000 registrations */
#ifdef CONFIG_DM9000
static struct resource s5p_dm9000_resources[] = {
[0] = {
.start = S5P_PA_DM9000,
.end   = S5P_PA_DM9000,
.flags = IORESOURCE_MEM,
},
[1] = {
#if defined(CONFIG_DM9000_16BIT)
.start = S5P_PA_DM9000 + 4,
.end   = S5P_PA_DM9000 + 4,
.flags = IORESOURCE_MEM,
#else
.start = S5P_PA_DM9000 + 1,
.end   = S5P_PA_DM9000 + 1,
.flags = IORESOURCE_MEM,
#endif
},
[2] = {
.start = IRQ_EINT9,
.end   = IRQ_EINT9,

.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
}
};


而我的电路图是EINT0,电路图如下





       所以我应该把IRQ_EINT9换成IRQ_EINT0 ,cmd 我接的是Xm0ADDR2,根据DM9000 数据手册

DM9000的访问地址主要是由CMD和CS#这两个端口的连接方式来确定的,CS#是DM9000的片选引脚,CMD引脚在芯片手册中描述如下:
CMD pin :
Command Type
When high, the access of this command cycle is DATA port
When low, the access of this command cycle is INDEX port

所以下面的这个部分不用改,刚好和我的硬件对应上

.start = S5P_PA_DM9000 + 4,
.end   = S5P_PA_DM9000 + 4,  

这个不用改。这里要说一下题外话,一些人对.end   = S5P_PA_DM9000 + 4这个有疑惑,一些人会用.end   = S5P_PA_DM9000 + 7 这个值,这里我来说一下我的理解,我觉得.end   = S5P_PA_DM9000 + 4,  以及.end   = S5P_PA_DM9000 + 7,  一样在Sate210 上能用,因为这个.end   = S5P_PA_DM9000 + 4,   只是地址空间长短的问题,这个dm9000 只要指向data port 地址已经足够,如果.end   = S5P_PA_DM9000 + 7  也只是浪费内存空间。

并且我的DM9000 的CS 连接到S5pv210 的Xm0CSn1 总线上,属于SROM 的bank1

那么根据S5pv210 的内存 布局(MEMORY ADDRESS MAP )如图


Sate210 dm9000 index port和data port 地址分别是

index port:0x88000000

data port :0x88000004

让我们来看看 S5P_PA_DM9000 的值是多少,如果不符合我们上述的标准,我们就要修改。

arch/arm/mach-s5pv210/include/mach/map.h 下有

#define S5PV210_PA_DM9000 (0x88000300)
#define S5P_PA_DM9000           S5PV210_PA_DM9000

居然是0x88000300 怎么回事呢?一般来说都会选择0x88000000 ,我认为这里替换成0x88000000也不会有关系的,因为真正决定DM9000 相关地址的不是这个“3”.不管怎么样,试了再说了。

            果然,改成#define S5PV210_PA_DM9000 (0x88000000) 也和原来的结果一样,一旦插上网线就不停的产生DM9000 中断,这个说明改成

#define S5PV210_PA_DM9000 (0x88000300)和#define S5PV210_PA_DM9000(0x88000000) 是一样的。

            为什么会不停的打印中断呢?是我的中断没设置对?除了上面

                .start = IRQ_EINT0,
.end   = IRQ_EINT0,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,

的难道还有别的设置要设置的?

              但是据我学习android 驱动的这段日子,这个配置已经足够了,因为IRQ_REQUEST 这个函数是会去调用中断号去下层配置的。这个在S5pv210 的矩阵键盘驱动我已经看清楚明白。

             为了证实我的想法,我飞线DM9000 到XEINT4 去,把中断改成

                .start = IRQ_EINT4,
.end   = IRQ_EINT4,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,

       神奇啊,Sate210 居然可以上网了,我改成XEINT2,XEINT9,XEINT5 都一样。就是改成XEINT0 就会插上网线就死机。这时候我感觉到这个应该不是dm9000 驱动和配置的问题,而是android下S5pv210 的IRQ中断向量寄存器的部分的程序问题,难道是三星的BUG?!我的天啊,这种事情我们遇到太多了,只要我们不参考三星官网的原理图设计,我们就会很吃亏,很久才能解决本来轻而易举的问题。于是我我又邀请做android的高手朋友帮我看代码,他们帮我远程协助搞到晚上一点钟,也没查出结果,后来师弟还说周日要赶过来帮我调试,让我感动的不知道如何是好,要知道我这是商业行为,对于师弟这种帮助,我感觉不知道怎么办。我知道他成天加班,并且人还不在广州,太远了,不太合适,把人家周末给抢夺了,我还是不想劳驾师弟过来帮我解决。于是我更加卖力的看代码,找到irq 部分的代码来看,两眼冒火了,就是没找出问题所在,我越看越兴奋,看的不舍得下班回家,这种状态我清晰的记得我当年刚毕业学wince就是这么样子的,我好开心,我的状态终于回来了。

        非常悲剧,又看了一晚上,还是没看出什么眉目,后来实在无奈了,拿出三星官方开发板的原理图来看看,发现有个惊人的信息:XEINT0 标了一个名字PSHOLD,这是啥玩意?看原理图只是三个插针,看三星官方开发板,上面挂着跳线帽,什么玩意啊,也没接什么东西。师弟晚上又在QQ问我:找到没有?我说貌似有点眉目,后来他说实在没办法的时候就看看手册。于是我去看了一下查XEINT0 的字眼,S5pv210 压根没有,我查找GPH 等字眼的时候才看到,于是用XEINT[0]去查找手册,惊人的一页出现了:

4.10.5.8  MISC Register (PS_HOLD_CONTROL, R/W, Address = 0xE010_E81C) 
PS_HOLD_CONTROL  Bit  Description  Initial State 
Reserved [31:12]  Reserved  0x00005 
Reserved [11:10]  Reserved  0 
DIR  [9]  Direction (0: input, 1: output)  1 
DATA  [8]  Driving value (0:low, 1:high)  0 
Reserved [7:1]  Reserved  0x00 
PS_HOLD_OUT_EN  [0]  XEINT[0] pad is controlled by this register values and 
values of control registers for XEINT[0] of GPIO 
chapter is ignored when this field is ‘1’.   
(0: disable, 1: enable) 

 
PS_HOLD (muxed with XEINT[0]) pin value is kept up in any power mode. This register is in alive region and reset 
by XnRESET or power off only.   
CONFIDENTIA


——幸好英文不是很差,一看就知道我错在哪里了,哎,手册没看详细的下场,这个问题其实很简单啊。

这上面说的意思就是S5pv210 的XEINT[0]引脚有复用功能的,这个引脚是一个非常特殊的引脚PS_HOLD 其实就是S5pv210 用来控制PMIC的,在任何S5pv210 处于任何电源模式下,这个引脚都能保持住我们给他设置的电平。

       果然啊,在mach-smdk110.c 下有

static void smdkc110_power_off(void)
{
/* PS_HOLD output High --> Low */
writel(readl(S5PV210_PS_HOLD_CONTROL_REG) & 0xFFFFFEFF,
S5PV210_PS_HOLD_CONTROL_REG);


while (1);
}

  在uboot下也有

/* To hold max8698 output before releasing power on switch,
         * set PS_HOLD signal to high
         */
        ldr     r0, =0xE010E81C  /* PS_HOLD_CONTROL register */
        ldr     r1, =0x00005301  /* PS_HOLD output high */
        str     r1, [r0]


uboot已经把 这个XEINT[0]引脚设置成PS_HOLD 功能,并让他一直输出高电平。

难怪我在devs.c 里面设置XEINT[0] 是高电平触发中断的时候他会不停的中断!原来如此! 不过有一点我疑问了,居然是设置成PS_HOLD 功能了,为什么XEINT[0] 中断功能还有效呢?这不是坑人吗?fuck 三星!搞死我了。

       现在我知道怎么解决了,在 smdkc110_dm9000_set(void) 函数加上:

static void __init smdkc110_dm9000_set(void)
{
unsigned int tmp;

writel(readl(S5PV210_PS_HOLD_CONTROL_REG) & 0x5000,S5PV210_PS_HOLD_CONTROL_REG);


tmp = ((0<<28)|(3<<24)|(7<<16)|(1<<12)|(3<<8)|(6<<4)|(0<<0));
__raw_writel(tmp, (S5P_SROM_BW+0x08));//Bank1

tmp = __raw_readl(S5P_SROM_BW);
tmp &= ~(0xf << 4);



tmp |= (0x1 << 4);
tmp |= (0x2 << 4);


__raw_writel(tmp, S5P_SROM_BW);


tmp = __raw_readl(S5PV210_MP01CON);
tmp &= ~(0xf << 4);
tmp |= (2 << 4);


__raw_writel(tmp, S5PV210_MP01CON);
}

重新make ,然后fastboot 烧写Sate210 zImage,发现DM9000 的中断慢下来了。

进入系统,打开uc 浏览器,O(∩_∩)O哈哈哈~终于可以上网了,连续不关机一天一夜,还是稳定的上网,看来稳定性还是不错的。自从这个Sate210 android DM9000 驱动调试告一段路。

        这是我这个android菜鸟首次单独解决这种bug ,非常高兴,写下这种吐槽调试经历,给自己做个纪念。欢迎广大网友丢砖头指导我,偶一定会再接再厉。

         

你可能感兴趣的:(原创S5PV210,Sate210开发板,Android,android,wince,output,三星,command,cmd)