移植CS8900A网卡驱动到GEC2440开发板
(2010-04-20 15:15:21)
转载
标签:
分类:
嵌入式Linux(ARM)
步骤:
设置好交叉编译工具链,Linux内核是前面移植的 2.6.32.8版本,在原来移植修改后的基础上进入下面操作。
(开发板上的10M网卡是CS8900A-CQ3Z),该内核版本的cs89x0.c和cs89x0.h文件只需修改小部分就可用。
根据原理图可知网卡的地址和中断号是分别是:0x19000000、EINT9/GPG1。
1、修改driver/net/cs89x0.c文件
1)、修改ioaddr和irq,接CS3,addr24选择io或memory方式,irq是EINT9/GPG1,写网卡MAC地址
在#include "cs89x0.h"后添加如下内容:
#include "../../arch/arm/mach-s3c2410/include/mach/map.h"
#include "../../arch/arm/mach-s3c2410/include/mach/regs-mem.h"
#include "../../arch/arm/mach-s3c2410/include/mach/regs-gpio.h"
#include "../../arch/arm/mach-s3c2410/include/mach/regs-irq.h"
在
#else
static unsigned int netcard_portlist[] __used __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
static unsigned int cs8900_irq_map[] = {10,11,12,5};
#endif
前添加如下代码:
#elif defined(CONFIG_ARCH_S3C2410)
static unsigned int netcard_portlist[] __used __initdata = { S3C24XX_VA_CS8900_CS3 + 0x300, 0};
static unsigned int cs8900_irq_map[] = {IRQ_EINT9,0,0,0};
2)、添加2440硬件初始化函数
在上面的后面添加如下函数内容:
static void cs89x0_hw_setup(struct net_device *dev)
{
unsigned int regval = 0;
//CS3, 16 bit bus width
__raw_writel(0x2211d110,S3C2410_BWSCON);
__raw_writel(0x1f7c,S3C2410_BANKCON3);
//EINT[9]
regval = __raw_readl(S3C2410_GPGCON);
regval &= ~(3<<2);
regval |= 2 <<2;
__raw_writel(regval, S3C2410_GPGCON);
//irq mode
regval = __raw_readl(S3C2410_EXTINT1);
regval &= ~(7<<4);
regval |= 4 <<4;
__raw_writel(regval, S3C2410_EXTINT1);
//irq MASK
regval = __raw_readl(S3C2410_EINTMASK);
regval &= ~(1<<9);
__raw_writel(regval, S3C2410_EINTMASK);
//mac addr
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0xc0;
dev->dev_addr[3] = 0xff;
dev->dev_addr[4] = 0xee;
dev->dev_addr[5] = 0x08;
printk("[cs89x0_probe] S3C2410_BWSCON = %x
", __raw_readl(S3C2410_BWSCON));
printk("[cs89x0_probe] S3C2410_BANKCON3 = %x
", __raw_readl(S3C2410_BANKCON3));
printk("[cs89x0_probe] S3C2410_GPGCON = %x
", __raw_readl(S3C2410_GPGCON));
printk("[cs89x0_probe] S3C2410_EXTINT1 = %x
", __raw_readl(S3C2410_EXTINT1));
printk("[cs89x0_probe] S3C2410_EINTMASK = %x
", __raw_readl(S3C2410_EINTMASK));
printk("[cs89x0_probe] MAC ADDR: %x-%x-%x-%x-%x-%x
",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
}
3)、在cs89x0_probe函数里调用cs89x0_hw_setup函数
在文件中如下代码
if (net_debug)
printk("cs89x0:cs89x0_probe(0x%x)
", io);
前添加如下代码:
cs89x0_hw_setup(dev);
4)、修改readword,writeword函数,portno不需要左移 (下面不用改,因为执行else分支里面的就是下面内容)
static u16 readword(unsigned long base_addr, int portno)
{
return __raw_readw(base_addr+portno);
}
static void writeword(unsigned long base_addr, int portno,u16 value)
{
__raw_writew(value,base_addr+portno);
}
5)、设置网口RJ45,省去boot启动时带参数
lp->force = g_cs89x0_media__force;
改成
lp->force=FORCE_RJ45;
6)、注释掉irq_map的安全检查
#if 0
if (((1 <<>irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x
",
dev->name, dev->irq, lp->irq_map);
ret = -EAGAIN;
goto bad_out;
}
#endif
2、2440初始化时增加分配cs8900的io port,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件:
static struct map_desc smdk2440_iodesc[] __initdata = {
{
.virtual = (u32)S3C24XX_VA_ISA_WORD,
.pfn = __phys_to_pfn(S3C2410_CS2),
.length = 0x10000,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
.pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
.length = SZ_4M,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_BYTE,
.pfn = __phys_to_pfn(S3C2410_CS2),
.length = 0x10000,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
.pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
.length = SZ_4M,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_CS8900_CS3,
.pfn = __phys_to_pfn(S3C2410_CS3 + (1<<24)),
.length = SZ_1M,
.type = MT_DEVICE,
}
};
3、在arch/arm/mach-s3c2410/include/mach/map.h增加宏定义,跟别的不冲突就行了
#define S3C24XX_VA_CS8900_CS3 S3C2410_ADDR(0x04000000)
4、修改driver/net/Kconfig文件:
config CS89x0
tristate "CS89x0 support"
depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351
|| ARCH_IXDP2X01 || ARCH_PNX010X || MACH_MX31ADS) || ARCH_S3C2410
5、重新配置内核
make menuconfig
配置如下项:
Device Drivers --->
Network device support --->
Ethernet (10 or 100 Mbit) --->
<*> CS89x0 support
Device Drivers --->
Generic Driver Options --->
[*] Create a kernel maintained /dev tmpfs (EXPERIMENTAL)
[*] Automount devtmpfs at /dev
make zImage
重新生成zImage镜像文件,再烧写到Nand Flash中。
运行时提示下面内容:
[cs89x0_probe] S3C2410_BWSCON = 2211d110
[cs89x0_probe] S3C2410_BANKCON3 = 1f7c
[cs89x0_probe] S3C2410_GPGCON = ff95ffba
[cs89x0_probe] S3C2410_EXTINT1 = 40
[cs89x0_probe] S3C2410_EINTMASK = fffdf0
[cs89x0_probe] MAC ADDR: 0-0-c0-ff-ee-8
cs89x0:cs89x0_probe(0x0)
cs89x0.c: v2.4.3-pre1 Russell Nelson
, Andrew Morton
eth0: cs8900 rev K found at 0xf8000300
cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line
cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 00:00:c0:ff:ee:08
cs89x0_probe1() successful
[cs89x0_probe] S3C2410_BWSCON = 2211d110
[cs89x0_probe] S3C2410_BANKCON3 = 1f7c
[cs89x0_probe] S3C2410_GPGCON = ff95ffba
[cs89x0_probe] S3C2410_EXTINT1 = 40
[cs89x0_probe] S3C2410_EINTMASK = fffdf0
[cs89x0_probe] MAC ADDR: 0-0-c0-ff-ee-8
cs89x0:cs89x0_probe(0x0)
cs89x0: request_region(0xf8000300, 0x10) failed
cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP
运行时有上面的提示,并且找不到/dev/eth0设备,但可以查看到/proc/net/dev/目录下多了eth0一项,可以通过ifconfig设置,并且可以ping通上位机。如下截图:
主机去Ping也可以通,证明驱动没问题,如下截图:
参考网址:http://blog.ednchina.com/nino61/240010/message.aspx
http://www.ourcn.cn/Linuxzhuanti/guanliyingyong/2009-11-20/8754.html
http://zhubangbing.blog.163.com/blog/static/52609270200811224645613/
http://blog.chinaunix.net/u3/93882/showart_1869908.html
http://blog.csdn.net/fei1700/archive/2008/11/28/3395619.aspx