linux 2.6.24.4在S3C2410上的移植(CS8900网卡驱动)(基于GEC2410)

SMDK2410配置默认使用的是DM9000A的网卡,因此我们需要修改成CS8900A的网卡驱动.
网上找到移植方法有两种方法,一种是将以前版本的cs8900.c驱动拿过来用,只要在配置中增加ARM_CS8900选项,这个代码网上有很多,拿过来试了以下,的确没问题.
另一种方法是修改2.6.24.4自带的cs89x0.c驱动,这个驱动没有2410的直接支持,我们需要修改.
这里采用第二种方法.参考了网上很多方法,将我的步骤整理如下,如有错误,欢迎指正.
1.内核配置菜单
由于cs89x0驱动依赖于NET_PCI,见drivers/net/Kconfig
depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
这里我们在SMDK配置中选择上NET_PCI和ISA即可.
修改arch/arm/mach-s3c2410/Kconfig,增加NET_PCI和ISA的选择
config ARCH_SMDK2410
 bool "SMDK2410/A9M2410"
 select CPU_S3C2410
 select MACH_SMDK
 select NET_PCI
 select ISA

 help
    Say Y here if you are using the SMDK2410 or the derived module A9M2410
 

然后运行内核配置:
[matt@localhost linux-2.6.24.4]$ make menuconfig
在Device Drivers-Network Device Support中选中CS89x0 support
[*]Ethernet (10 or 100Mbit) --->
   .......
    -*-   EISA, VLB, PCI and on board controllers                    │ │  
      < >     Ansel Communications EISA 3200 support (EXPERIMENTAL)    │ │  
      < >     Apricot Xen-II on board Ethernet                         │ │  
      < >   Broadcom 440x/47xx ethernet support                        │ │  
      <*>   CS89x0 support     
                                    
2.修改cs89x0.c
(1)修改include/asm/arch-s3c2410/map.h
添加如下CS8900地址(物理地址,虚拟地址)定义
/* CS8900 */
#define S3C24XX_VA_CS8900 S3C2410_ADDR(0x01300000)
#define S3C2410_PA_CS8900 (0x19000000)
#define S3C24XX_SZ_CS8900 SZ_1M
#define S3C24XX_PA_CS8900 S3C2410_PA_CS8900

这里定义了网卡使用的物理地址(S3C2410_PA_CS8900 )还有虚拟地址(S3C24XX_VA_CS8900),其中S3C2410_ADDR定义在include/asm/plat-s3c/map.h,实际上就是基址加偏移,CS8900的虚拟地址起始地址就等于0xf5300000
#define S3C_ADDR_BASE (0xF4000000)
#ifndef __ASSEMBLY__
#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x))
#else
#define S3C_ADDR(x) (S3C_ADDR_BASE + (x))
#endif
(2)修改arch/arm/mach-s3c2410/mach-s3c2410.c
在static struct map_desc smdk2410_iodesc[] __initdata作如下修改,进行地址映射.
static struct map_desc smdk2410_iodesc[] __initdata = {
         IODESC_ENT(CS8900)
};

IODESC_ENT是一个宏,定义在include/asm/plat-s3c24xx/cpu.h
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
展开实际上相当于
static struct map_desc smdk2410_iodesc[] __initdata = {
    {(unsigned long)S3C24XX_VA_CS8900,
      __phys_to_pfn(S3C24XX_PA_CS8900)
      S3C24XX_SZ_CS8900,
      MT_DEVICE};
}; 
(3)修改drivers/net/cs89x0.c文件
在声明头文件处添加头文件:
#ifdef CONFIG_ARCH_S3C2410
#include
#include
#include
#include
#endif 

在定义netcard_portlist和cs8900_irq_map代码中添加针对CONFIG_ARCH_S3C2410的定义,设置地址映射和IRQ,其中DEFAULTIOBASE(定义在cs89x0.h)是cs8900IO基址(0x300),这样cs8900的IO虚拟地址就是0xf5300300(0xf5300000+0x300)

#elif defined(CONFIG_ARCH_S3C2410)
static unsigned int netcard_portlist [] __initdata = { S3C24XX_VA_CS8900 + DEFAULTIOBASE, 0 };
static unsigned int cs8900_irq_map[] = { IRQ_EINT9, 0, 0, 0 };
  #ifdef request_region
   #undef request_region
   #endif
   #ifdef release_region
   #undef release_region
   #endif
   #define request_region(a, s, n) request_mem_region(a, s, n)
   #define release_region(a, s) release_mem_region(a, s)
 
#else
static unsigned int netcard_portlist[] __initdata =
   { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
static unsigned int cs8900_irq_map[] = {10,11,12,5};
在cs89x0_probe函数irq = dev->irq一句后添加:
io = dev->base_addr;
irq = dev->irq;
#ifdef CONFIG_ARCH_S3C2410  __raw_writel((__raw_readl(S3C2410_GPGCON)&~(0x3<<2))|(0x2<<2),S3C2410_GPGCON);
__raw_writel((__raw_readl(S3C2410_EXTINT1)&~(0x7<<4))|(0x4<<4),S3C2410_EXTINT1);
#endif

这段代码用来设置s3c2410 GPIO寄存器,设置EINT9为外部中断(CS8900的中断输入),上升沿触发,寄存器具体含义可参考s3c2410的datasheet.

在cs89x0_probe1函数reset_chip(dev)后设置网卡的MAC地址,设置成与u-boot一样的MAC地址.
reset_chip(dev);
#ifdef CONFIG_ARCH_S3C2410
     lp->force = FORCE_RJ45;
     lp->auto_neg_cnf = IMM_BIT;

     dev->dev_addr[0] = 0x12; 
     dev->dev_addr[1] = 0x24;
     dev->dev_addr[2] = 0x56;
     dev->dev_addr[3] = 0x78;
     dev->dev_addr[4] = 0x9a;
     dev->dev_addr[5] = 0xbc;
#endif


在net_open函数的if (((1 << dev->irq) & lp->irq_map) == 0) 前的if判断添加针对CONFIG_ARCH_S3C2410的判断,如下:
#if !defined(CONFIG_ARCH_S3C2410) && !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
  if (((1 << dev->irq) & lp->irq_map) == 0) {
   ......

至此修改完毕,编译后生成uImage,tftp到开发板可以ping和被ping
NAND read: device 0 offset 1048576, size 2097152 ...
 2097152 bytes read: OK
## Booting image at 30008000 ...
   Image Name:   linux-2.6.24
   Created:      2010-05-25   7:22:51 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1572120 Bytes =  1.5 MB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK

Starting kernel ...

Uncompressing Linux....................................................................................................... done, booting the kernel.
Linux version 2.6.24.4 (matt@localhost) (gcc version 3.4.5) #58 Tue May 25 15:20:22 CST 2010
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177
Machine: SMDK2410
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410A (id 0x32410002)
S3C2410: core 200.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
irq: clearing subpending status 00000002
PID hash table entries: 256 (order: 8, 1024 bytes)
timer tcon=00500000, tcnt a2c1, tcfg 00000200,00000000, usec 00001eb8
Console: colour dummy device 80x30
console [ttySAC0] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 61568KB available (2892K code, 317K data, 136K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 64 bytes
NET: Registered protocol family 16
S3C2410 Power Management, (c) 2004 Simtec Electronics
S3C2410: Initialising architecture
S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics
DMA channel 0 at c4800000, irq 33
DMA channel 1 at c4800040, irq 34
DMA channel 2 at c4800080, irq 35
DMA channel 3 at c48000c0, irq 36
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NetWinder Floating Point Emulator V0.97 (double precision)
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach
s3c2410-lcd: probe of s3c2410-lcd failed with error -22
lp: driver loaded but no devices found
ppdev: user-space parallel port driver
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled
s3c2410-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
s3c2410-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
s3c2410-uart.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
loop: module loaded
cs89x0:cs89x0_probe(0x0)
cs89x0.c: v2.4.3-pre1 Russell Nelson <
[email protected]>, Andrew Morton <[email protected]>
eth0: cs8900 rev K found at 0xf5300300
cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line
cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 12:24:56:78:9a:bc
cs89x0_probe1() successful
cs89x0:cs89x0_probe(0x0)
cs89x0: request_region(0xf5300300, 0x10) failed
cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP

Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
BAST NOR-Flash Driver, (c) 2004 Simtec Electronics
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410-nand s3c2410-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=3 30ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
NAND_ECC_NONE selected by board driver. This is not recommended !!
Scanning device for bad blocks
Creating 4 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00100000 : "U-Boot"
0x00100000-0x00400000 : "Linux Kernel"
0x00400000-0x02c00000 : "Root"
0x02c00000-0x04000000 : "User"
usbmon: debugfs is not available
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
mice: PS/2 mouse device common for all mice
S3C24XX RTC, (c) 2004,2006 Simtec Electronics
s3c2410-i2c s3c2410-i2c: slave address 0x10
s3c2410-i2c s3c2410-i2c: bus frequency set to 390 KHz
s3c2410-i2c s3c2410-i2c: i2c-0: S3C I2C adapter
S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics
s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
TCP cubic registered
NET: Registered protocol family 1
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 136K
init started: BusyBox v1.10.1 (2010-05-26 13:19:35 CST)
starting pid 775, tty '/dev/console': ' /etc/init.d/rcS'
eth0: using half-duplex 10Base-T (RJ-45)
starting pid 780, tty '/dev/ttySAC0': ' /bin/sh'
(根文件系统的制作将在下一篇介绍)
其中出现了cs89x0: request_region(0xf5300300, 0x10) failed,查找了很多文章,这个问题不大.至于是否有严重影响,留待进一步检验.
ping和被ping都没有问题.
# ping 192.168.1.15
PING 192.168.1.15 (192.168.1.15): 56 data bytes
84 bytes from 192.168.1.15: icmp_seq=0 ttl=128 time=2.9 ms
84 bytes from 192.168.1.15: icmp_seq=1 ttl=128 time=0.9 ms
84 bytes from 192.168.1.15: icmp_seq=2 ttl=128 time=0.9 ms
84 bytes from 192.168.1.15: icmp_seq=3 ttl=128 time=0.9 ms


你可能感兴趣的:(Embedded,Linux)