[6410]移植dm9000ae驱动到u-boot
刚到手的友坚6410开发板的u-boot竟然没有网卡驱动,无语,自己做吧。
u-boot版本1.1.6
(1)在smdk6410.h中注释掉CS8900信息,添加DM9000信息
注意参考原理图,DM9000使用了CSn1,基地址为18000000
//#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