移植dm9000ae驱动到u-boot

时间:2022-05-18 17:12:53

[6410]移植dm9000ae驱动到u-boot


u-boot版本1.1.6

(1)在smdk6410.h中注释掉CS8900信息,添加DM9000信息
注意参考原理图,DM9000使用了CSn1,基地址为18000000

 

移植dm9000ae驱动到u-boot

//#define CONFIG_DRIVER_CS8900 0 /* we have a CS8900 on-board */
//#define CS8900_BASE   0x18800300
//#define CS8900_BUS16   1 /* the Linux driver does accesses as shorts */
//#endif

#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x18000300 //0x20000300
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4)
#define CONFIG_DM9000_USE_16BIT

(2)编译,测试,出现以下问题,MAC不对
kyon6410 # ping 192.168.0.1
dm9000 not found at 0x0112a9ac id: 0x24242424
MAC: 24:24:24:24:24:24
operating at 10M full duplex mode
rx fifo error
rx crc error
rx length too big

ARP Retry count exceeded; starting again
rx fifo error
rx crc error
rx length too big

在dm9000x.c中注释以下内容:

/* Set Node address */
/* for (i = 0; i < 6; i++)
   ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
*/

添加以下内容,后来用了1.3.3的dm9000x.c文件,发现已经有了。
        char *s, *e;
        s = getenv ("ethaddr");
        for (i = 0; i < 6; ++i)
{
            bd->bi_enetaddr[i] = s ?
                simple_strtoul (s, &e, 16) : 0;
            if (s)
                s = (*e) ? e + 1 : e;
        }
// kyon


继续测试:

kyon6410 # ping 192.168.0.1
dm9000 not found at 0x0112a9ac id: 0x24242424
MAC: 00:40:5c:26:0a:5b
operating at 10M full duplex mode
rx fifo error
rx crc error
rx length too big

ARP Retry count exceeded; starting again
rx fifo error
rx crc error
rx length too big

MAC地址读出来了,其他还是不对

然后发现0x18000000写成18000000了,囧

(3)将地址修改为0x18000000,继续:

dm9000 i/o: 0x18000300, id: 0x90000a46
MAC: 00:40:5c:26:0a:5b
operating at 100M full duplex mode

能正确识别网卡,ping不通

注释以下内容:
#if 0
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
   udelay(1000);
   i++;
   if (i == 10000) {
    printf("could not establish link/n");
    return 0;
   }
}
#endif

注释后省去检查网卡的过程,还是不行,tftp貌似只能传一个数据包。

(4)打开调试宏进行调试,网上还有人可能是bank没有被正确配置为16bit宽度导致问题。
查看smdk6410.c,发现已经正确初始化了CSn1,虽然用的是CS8900的代码:
/* ------------------------------------------------------------------------- */
#define CS8900_Tacs (0x0) // 0clk   address set-up
#define CS8900_Tcos (0x0) // 4clk   chip selection set-up
#define CS8900_Tacc (0x7) // e 14clk access cycle
#define CS8900_Tcoh (0x0) // 1clk   chip selection hold
#define CS8900_Tah (0x0) // 4clk   address holding time
#define CS8900_Tacp (0x0) // 6clk   page mode access cycle
#define CS8900_PMC (0x0) // normal(1data)page mode configuration

static void cs8900_pre_init(void)
{
SROM_BW_REG &= ~(0xf << 4);
SROM_BW_REG |= (1<<7) | (1<<6) | (1<<4);
SROM_BC1_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));
}

顺便按照资料优化了一下总线时序,dm9000很快的。


(5)以上是昨晚的调试过程,非常郁闷的回去睡觉了。早上过来想看看mini2440的原理图,看看他们怎么做的。
结果被郁闷到了,原来mini2440使用的是dm9000,我这里的芯片是dm9000ae!两者引脚都不一样!
在网上搜索dm9000ae,发现许多人都是按照dm9000的方法移植,都出现我昨晚的问题,能够识别,ping不通。

(6)
无奈参考Linux内核中代码,发现Linux的dm9000在rx函数中添加do while循环,于是按照Linux内核源码在u-boot中也添加do while循环。
do{
/* Check packet ready or not */
DM9000_ior(DM9000_MRCMDX); /* Dummy read */
rxbyte = DM9000_inb(DM9000_DATA); /* Got most updated data */
if (rxbyte == 0)
   return 0;

/* Status check: this byte must be 0 or 1 */
if (rxbyte > 1) {
   DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
   DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
   DM9000_DBG("rx status check: %d/n", rxbyte);
}
DM9000_DBG("receiving packet/n");

/* A packet ready now & Get status/length */
DM9000_outb(DM9000_MRCMD, DM9000_IO);

     /* */
RxStatus = DM9000_inw(DM9000_DATA);
RxLen = DM9000_inw(DM9000_DATA);

     /* */
DM9000_DBG("rx status: 0x%04x rx len: %d/n", RxStatus, RxLen);

/* Move data from DM9000 */
/* Read received packet from RX SRAM */
tmplen = (RxLen + 1) / 2;
for (i = 0; i < tmplen; i++)
   {
    ((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA);
    //printf("%d ",((u16 *) rdptr)[i]);
   }
     /* */
if ((RxStatus & 0xbf00) || (RxLen < 0x40)
     || (RxLen > DM9000_PKT_MAX)) {
   if (RxStatus & 0x100) {
    printf("rx fifo error/n");
   }
   if (RxStatus & 0x200) {
    printf("rx crc error/n");
   }
   if (RxStatus & 0x8000) {
    printf("rx length error/n");
   }
   if (RxLen > DM9000_PKT_MAX) {
    printf("rx length too big/n");
    dm9000_reset();
   }
} else {

   /* Pass to upper layer */
   DM9000_DBG("passing packet to upper layer/n");
   NetReceive(NetRxPackets[0], RxLen);
   //return RxLen;
}
}
while (rxbyte == DM9000_PKT_RDY);
//return 0;

return RxLen;

测试结果:
大部分时候都可以ping通了,因为有调试信息,tftp速度十几k。

网上还有个建议在tx函数前加入以上内容清空dm9000ae寄存器
DM9000_ior(DM9000_MRRH);
DM9000_ior(DM9000_MRRL);

我放在do的前面,貌似也有一定作用


(7)
每次ping结束后都会进入eth_halt,关闭网络,可能导致传输出现问题,遂屏蔽halt函数内容。
void
eth_halt(void)
{
DM9000_DBG("eth_halt dummy by kyon/n");

/* RESET devie */
//phy_write(0, 0x8000); /* PHY RESET */
//DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
//DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
//DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
}

(8)至此dm9000ae基本能够使用,只是用来加载内核已经足够了。
测试传输速度有1.2MB,很快!


U-Boot 1.1.6 (Jul 8 2009 - 11:31:24) for SMDK6410

****************************************
**    UT-S3C6410 Nand boot v0.18      **
**    ShenZhen Urbetter Technology    **
**   
Http://www.urbetter.com         **
****************************************

CPU:     S3C6410@532MHz
         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board:   SMDK6410
DRAM:    128 MB
Flash:   0 kB
NAND:    256 MB
In:      serial
Out:     serial
Err:     serial
Hit any key to stop autoboot: 0
dm9000 i/o: 0x18000300, id: 0x90000a46
MAC: 00:40:5c:26:0a:5b
operating at 100M full duplex mode
TFTP from server 192.168.0.1; our IP address is 192.168.0.4
Filename 'zimage'.
Load address: 0xc0008000
Loading: T #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############################
done
Bytes transferred = 1813092 (1baa64 hex)
Boot with zImage

Starting kernel ...

Uncompressing Linux...................................................................................................................... done, booting the kernel.
Linux version 2.6.24.2 (
fusq@fusq-urbetter) (gcc version 4.2.2) #343 Sat Jun 20 13:24:05 CST 2009
CPU: ARMv6-compatible processor [410fb766] revision 6 (ARMv7), cr=00c5387f
Machine: SMDK6410