S3C6410移植linux-2.6.39 笔记(四)-dm9k驱动移植

时间:2023-02-08 12:22:13

Author:    eilian

Blog:       http://blog.csdn.net/eilianlau

Copyright:Original

Date:   2011、12、15

1、Hosting environment:VMare ubuntu10.04 

2、Cross-compiling environment:arm-2009q3.tar.bz2

3、Development board:QT6410

4、nanflash:K9F2G08(256M)

5、linux -version:Linux-2.6.39

6、uboot-version:u-boot-2010.06

三天了,当每一次编译到drivers/net/dm900.o的时候我心跳就开始加速了,漫长的编译,每一次算15分钟,昨天我移植LCD驱动的时候,至少编译了5次以上,痛苦。

前些天虽然就把dm900驱动移植成功了,但是有个小问题,就是文件系统启动后不能ping,更不能挂载nfs文件系统,表示鸭梨大,所以这篇文章一直拖了好几天,

今天经过两次的编译中下能从nfs启动文件系统,能实现各种网卡命令了,赶紧写个记录。

网卡驱动在/drivers/net/目录下,QT6410用的是dm9000ae芯片,/drivers/net/dm900.c驱动文件和CPU无关,并且dm900.c是基于平台驱动架构的,在QT6410开发板上,dm9000ae直接接在了S3C6410的存储器总线上,原理图如下:

S3C6410移植linux-2.6.39 笔记(四)-dm9k驱动移植

DM9000AE CMD控制引脚接在S3C6410片选信号1上,即bank1上所以DM9000的基地址就是0x18000000(物理地址)

移植步骤:

1)dm9000ae驱动程序既然与CPU无关,那么移植的时候肯定要初始化dm9000ae所接的GPIO,由上图可以看出,对于SROM的初始化已经的在uboot中实现

这里只需要初始化IRQ_LAN引脚,即EINT7(GPN7),所以需要将GPN7配置成外部中断引脚,并配置外部中断寄存器使能中断,EINT7由S3C6410芯片手册可知

是属于第0组外部中断

修改dm9000.c,增加GPIO初始化代码

/*
 * dm9k on QT6410 development board gpio init
 */
static void init_dm9k_gpio(){
    //配置GPN7为外部中断引脚
    writel((readl(S3C64XX_GPNCON) & ~(0x3 <<14)) | (0x2 << 14), S3C64XX_GPNCON);    /* GPN7 to EINT */
    writel((readl(S3C64XX_GPNPUD) &~(0x3<<14)),S3C64XX_GPNPUD);
//设置EINT7高电平触发中断
    writel((readl(S3C64XX_EINT0CON0) & ~(0x7 <<12)) | (0x1 << 12), S3C64XX_EINT0CON0);        /* EINT7 to high level triggered */
  writel((readl(S3C64XX_EINT0FLTCON0)& ~(0x3 <<6)) | (0x1 << 7), S3C64XX_EINT0FLTCON0);
    writel((readl(S3C64XX_EINT0PEND)&~(0x1<<7)),S3C64XX_EINT0PEND);    
    /* 使能中断 */
    writel(readl(S3C64XX_EINT0MASK) & ~(0x1 << 7), S3C64XX_EINT0MASK);        
}

static int __devinit dm9000_probe(struct platform_device *pdev)探测函数中调用上述初始化代码

/*
 * Search DM9000 board, allocate space and register it
 */
static int __devinit dm9000_probe(struct platform_device *pdev)
{
    struct dm9000_plat_data *pdata = pdev->dev.platform_data;
    struct board_info *db;    /* Point a board information structure */
    struct net_device *ndev;
    const unsigned char *mac_src;
    int ret = 0;
    int iosize;
    int i;
    u32 id_val;
    init_dm9k_gpio();
    /* Init network device */
    ndev = alloc_etherdev(sizeof(struct board_info));

   //..修改后需要添加必要的头文件要不编译会报错

}

在dm9000.c中添加如下头文件

#include <plat/gpio-cfg.h>
#include <mach/map.h>
#include <asm/gpio.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>

dm9000在bsp中作为平台驱动出现,这里参考arch/arm/mach-s3c64xx/mach-real6410.c给dm9000平台驱动添加所需要的平台资源

arch/arm/mach-s3c64xx/mach-qt6410.c中添加如下代码

/* DM9000AE 10/100 ethernet controller */

#ifdef CONFIG_DM9000
static struct resource dm9000_resources[] = {
    [0] = {
        .start        =
S3C64XX_PA_XM0CSN1,
        .end        =
S3C64XX_PA_XM0CSN1 + 3,
        .flags        = IORESOURCE_MEM,
    },
    [1] = {
        .start        =
S3C64XX_PA_XM0CSN1 + 4,
        .end        =
S3C64XX_PA_XM0CSN1 +SZ_1M - 1,
        .flags        = IORESOURCE_MEM,
    },
    [2] = {
        .start        = IRQ_EINT(7),
        .end        = IRQ_EINT(7),
        .flags        = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
    },
};

static struct dm9000_plat_data dm9000_setup = {
    .flags            = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),//dm9000.h
    .dev_addr        = { 0x08, 0x90, 0x00, 0xa0, 0x90, 0x90 },//添加网卡地址
};

static struct platform_device s3c_device_dm9000 = {
    .name            = "dm9000",
    .id                = 0,
    .num_resources    = ARRAY_SIZE(dm9000_resources),
    .resource        = dm9000_resources,
    .dev            = {
        .platform_data = &dm9000_setup,
    }
};
#endif //#ifdef CONFIG_DM9000

//同理还需要添加头文件

#include <plat/map-base.h>
#include <linux/dm9000.h>

上面的S3C64XX_PA_XM0CSN1物理地址,增加dm9000平台资源所使用的资源的IO映射,linux内核操作的是虚拟地址,实际上就上建立一个映射表

在bsp(/arch/arm/mach-s3c64xx)目录下的mach-qt6410.c文件中建立dm9000平台资源所使用的IO映射表

static struct map_desc qt6410_iodesc[] = {
#ifdef CONFIG_DM9000
    {
        .virtual        = (u32)S3C64XX_VA_XM0CSN1,//dm9000IO基地址所对应的虚拟地址
        .pfn            = __phys_to_pfn(S3C64XX_PA_XM0CSN1),//物理地址转换成虚拟地址
        .length         = SZ_1M, //长度
        .type           = MT_DEVICE,                //类型
    },
#endif

};

不妨看看struct map_desc结构的定义在arch/arm/include/asm/mach/map.h中定义了
struct map_desc {
    unsigned long virtual;
    unsigned long pfn;
    unsigned long length;
    unsigned int type;
};

/* types 0-3 are defined in asm/io.h */
#define MT_UNCACHED        4
#define MT_CACHECLEAN        5
#define MT_MINICLEAN        6
#define MT_LOW_VECTORS        7
#define MT_HIGH_VECTORS        8
#define MT_MEMORY        9
#define MT_ROM            10
#define MT_MEMORY_NONCACHED    11
#define MT_MEMORY_DTCM        12
#define MT_MEMORY_ITCM        13

其中上面所用到的type=MT_DEVICE=0定义在arch/arm/include/asm/mach/io.h代表该类型为IO类型

同样的我们建立了虚拟地址到物理地址的映射表之后那么它又怎样和系统联系起来呢?看看/arch/arm/mach-s3c64xx/mach-qt6410.c中下面这两个函数(蓝色部分)

static void __init qt6410_map_io(void)
{
    u32 tmp;
    s3c64xx_init_io(qt6410_iodesc, ARRAY_SIZE(qt6410_iodesc));//初始化IO映射
    s3c24xx_init_clocks(12000000);
    s3c24xx_init_uarts(qt6410_uartcfgs, ARRAY_SIZE(qt6410_uartcfgs));
  。。。。。。。。。。。

MACHINE_START(QT6410, "QT6410 development board")
    /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
    .boot_params    = S3C64XX_PA_SDRAM + 0x100,

    .init_irq    = s3c6410_init_irq,
    .map_io        = qt6410_map_io,
    .init_machine    = qt6410_machine_init,
    .timer        = &s3c24xx_timer,
MACHINE_END

//当系统启动的时候最先执行的就是MACHINE_START(QT6410, "QT6410 development board"),同时会调用qt6410_map_io()而qt6410_map_io中又调用了s3c64xx_init_io(qt6410_iodesc,...)这样内核就会帮我们创建我们需要的页表了。更详细的过程请看我的另一篇转载文章及其经典,同时需要了解MMU想关的知识,因为在实际硬件操作的时候,MMU就充当着为我们创建页表的角色

添加虚拟地址的宏定义对s3c6410个寄存器的物理地址和虚拟地址的宏定义都在arch/arm/plat-samsung/include/plat/map-base.h(虚拟地址)和arch/arm/mach-s5p64x0/include/mach/map.h(虚拟地址&&物理地址)

arch/arm/plat-samsung/include/plat/map-base.h中添加

#define S3C_VA_IRQ    S3C_ADDR(0x00000000)    /* irq controller(s) */
#define S3C_VA_SYS    S3C_ADDR(0x00100000)    /* system control */
#define S3C_VA_MEM    S3C_ADDR(0x00200000)    /* memory control */
#define S3C_VA_TIMER    S3C_ADDR(0x00300000)    /* timer block */
#define S3C_VA_WATCHDOG    S3C_ADDR(0x00400000)    /* watchdog */
#define S3C_VA_UART    S3C_ADDR(0x01000000)    /* UART */

#define S3C64XX_VA_XM0CSN1    S3C_ADDR(0x03b00300)//关于这个值为什么是这样的这里不做解释 感兴趣的朋友可以参考我另外转载的关于io地址映射的文章,多看几次慢慢的你就明白了

Notes:该文红色部分为需要修改或者添加的地方,蓝色部分仅是为了说明.至此dm9000移植已经结束了,

----------编译测试

/home/eilian/development/Linux/linux-2.6.39# make menuconfig

│ │    [*] Networking support  --->  
  │ │    --- Networking support                                        
  │ │          Networking options  ---> 
  │ │    <*> Packet socket                                               
  │ │    <*> Unix domain sockets                                        
  │ │    < > Transformation user configuration interface              
  │ │    [ ] Transformation sub policy support (EXPERIMENTAL)          
  │ │    [ ] Transformation migrate database (EXPERIMENTAL)              
  │ │    [ ] Transformation statistics (EXPERIMENTAL)                   
  │ │    < > PF_KEY sockets                                            
  │ │    [*] TCP/IP networking                                           
  │ │    [*]   IP: multicasting                                          
  │ │    [ ]   IP: advanced router  
  │ │    [*]   IP: kernel level autoconfiguration                     
  │ │    [*]     IP: DHCP support                                        
  │ │    [*]     IP: BOOTP support                                   
  │ │    [*]     IP: RARP support                                      
  │ │    < >   IP: tunneling                                             
  │ │    < >   IP: GRE demultiplexer                                     
  │ │    [ ]   IP: multicast routing                                   
  │ │    [ ]   IP: ARP daemon support  
  │ │    < >   IP: ESP transformation                                 
  │ │    < >   IP: IPComp transformation                             
  │ │    <*>   IP: IPsec transport mode                               
  │ │    <*>   IP: IPsec tunnel mode                                   
  │ │    <*>   IP: IPsec BEET mode                                     
  │ │    <*>   Large Receive Offload (ipv4/tcp)                         
  │ │    <*>   INET: socket monitoring interface                       
  │ │    [ ]   TCP: advanced congestion control  --->                   
  │ │    [ ]   TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)
  │ │    <M>   The IPv6 protocol  --->    

  │ │        Device Drivers  --->   

  │ │    [*] Network device support  --->     

  │ │    [*]   Ethernet (10 or 100Mbit)  --->                               
  │ │    <*>   DM9000 support                                       
  │ │    (4)     DM9000 maximum debug level      
另外为了测试网卡移植,可以通过NFS文件系统来测试

  │ │        File systems  --->   
  │ │    [*] Network File Systems  --->                     
  │ │    --- Network File Systems                                     
  │ │    <*>   NFS client support                  //必须选上的                    
  │ │    [*]     NFS client support for NFS version 3       //必须选上的             
  │ │    [*]       NFS client support for the NFSv3 ACL protocol extension
  │ │    [*]     NFS client support for NFS version 4                    
  │ │    [ ]       NFS client support for NFSv4.1 (EXPERIMENTAL)     
  │ │    [*]   Root file system on NFS     //必须选上的
 │ │    <*>   NFS server support                                     
  │ │    [*]     Include support for deprecated syscall interface to NFSD
  │ │    -*-     NFS server support for NFS version 3                 
  │ │    [ ]       NFS server support for the NFSv3 ACL protocol extension
  │ │    [*]     NFS server support for NFS version 4 (EXPERIMENTAL)    
挂载NFS文件系统后

CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: QT6410 development board
Memory policy: ECC disabled, Data cache writeback
CPU S3C6410 (id 0x36410101)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
camera: no parent clock specified
S3C64XX: PLL settings, A=533000000, M=533000000, E=24000000
S3C64XX: HCLK2=266500000, HCLK=133250000, PCLK=66625000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 32512
Kernel command line: noinitrd root=/dev/nfs rw nfsroot=192.168.0.3:/home/eilian/development/workspace/rootfs-nfsip=192.168.0.4:192.168.0.1::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=128M
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 128MB = 128MB total
Memory: 125652k/125652k available, 5420k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xff600000 - 0xffe00000   (   8 MB)
    vmalloc : 0xc8800000 - 0xf6000000   ( 728 MB)
    lowmem  : 0xc0000000 - 0xc8000000   ( 128 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .init : 0xc0008000 - 0xc002a000   ( 136 kB)
      .text : 0xc002a000 - 0xc03af0b4   (3605 kB)
      .data : 0xc03b0000 - 0xc03dd5e0   ( 182 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS:246
VIC @f6000000: id 0x00041192, vendor 0x41
VIC @f6010000: id 0x00041192, vendor 0x41
Console: colour dummy device 80x30
console [ttySAC0] enabled
Calibrating delay loop... 531.66 BogoMIPS (lpj=2658304)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
s3c64xx_dma_init: Registering DMA channels
PL080: IRQ 73, at c8808000, channels 0..8
PL080: IRQ 74, at c880c000, channels 8..16
S3C6410: Initialising architecture
bio: create slab <bio-0> at 0
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
s3c-i2c s3c2440-i2c.0: slave address 0x10
s3c-i2c s3c2440-i2c.0: bus frequency set to 65 KHz
s3c-i2c s3c2440-i2c.0: i2c-0: S3C I2C adapter
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 4, 81920 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
UDP hash table entries: 128 (order: 0, 6144 bytes)
UDP-Lite hash table entries: 128 (order: 0, 6144 bytes)
NET: Registered protocol family 1
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
ROMFS MTD (C) 2007 Red Hat, Inc.
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
start plist test
end plist test
S3C_LCD clock got enabled :: 133.250 Mhz
LCD TYPE :: LTE480WV will be initialized
Window[0] - FB1: map_video_memory: clear ffd00000:000ff000
            FB1: map_video_memory: dma=57a00000 cpu=ffd00000 size=000ff000
Window[0] - FB2: map_video_memory: clear ffd7f800:0007f800
            FB2: map_video_memory: dma=57a7f800 cpu=ffd7f800 size=0007f800
Console: switching to colour frame buffer device 60x34
fb0: s3cfb frame buffer device
Window[1] - FB1: map_video_memory: clear ffc00000:000ff000
            FB1: map_video_memory: dma=57b00000 cpu=ffc00000 size=000ff000
Window[1] - FB2: map_video_memory: clear ffc7f800:0007f800
            FB2: map_video_memory: dma=57b7f800 cpu=ffc7f800 size=0007f800
fb1: s3cfb frame buffer device
Window[2] - FB1: map_video_memory: clear ffb80000:0007f800
            FB1: map_video_memory: dma=57980000 cpu=ffb80000 size=0007f800
fb2: s3cfb frame buffer device
Window[3] - FB1: map_video_memory: clear ffb00000:0007f800
            FB1: map_video_memory: dma=57000000 cpu=ffb00000 size=0007f800
fb3: s3cfb frame buffer device
jkq debug VIDCON0 is 353
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
s3c6400-uart.0: ttySAC0 at MMIO 0x7f005000 (irq = 16) is a S3C6400/10
s3c6400-uart.1: ttySAC1 at MMIO 0x7f005400 (irq = 20) is a S3C6400/10
s3c6400-uart.2: ttySAC2 at MMIO 0x7f005800 (irq = 24) is a S3C6400/10
s3c6400-uart.3: ttySAC3 at MMIO 0x7f005c00 (irq = 28) is a S3C6400/10
brd: module loaded
loop: module loaded
S3C NAND Driver, (c) 2008 Samsung Electronics
S3C NAND Driver is using hardware ECC.
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x000000000000-0x000000100000 : "Bootloader"
0x000000100000-0x000000600000 : "Kernel"
0x000000600000-0x000007e00000 : "User"
0x000007e00000-0x000010000000 : "File System"
dm9000 Ethernet Driver, V1.31
dm9000 dm9000.0: eth0: Features changed: 0x00004802 -> 0x00004002
eth0: dm9000a at c8826000,c8c00004 IRQ 108 MAC: 08:90:00:a0:90:90 (platform data)//其中这些打印信息来自dm9000.c

。。。。。。。。。。。。。。。。。。。。。。。。

dm9000 dm9000.0: eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
IP-Config: Complete:
     device=eth0, addr=192.168.0.4, mask=255.255.255.0, gw=255.255.255.255,
     host=192.168.0.4, domain=, nis-domain=(none),
     bootserver=192.168.0.1, rootserver=192.168.0.3, rootpath=
VFS: Mounted root (nfs filesystem) on device 0:11.
Freeing init memory: 136K
**************munt all***************
*************************************
********booting for QT6410 **********
Version:android-2.6.39
Author:eilian
Copyright:Original
Blog:http://blog.csdn.net/eilianlau
Date:2011.12.14
************************************

Please press Enter to activate this console.
Processing /etc/profile...
Set search library path in /etc/profile
Set user path in /etc/profile
-/bin/sh: PAT: not found
root@bootloader#ifconfig
eth0      Link encap:Ethernet  HWaddr 08:90:00:A0:90:90
          inet addr:192.168.0.4  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2399 errors:0 dropped:0 overruns:0 frame:0
          TX packets:829 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2388806 (2.2 MiB)  TX bytes:130962 (127.8 KiB)
          Interrupt:108 Base address:0x6000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@bootloader#ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3): 56 data bytes
64 bytes from 192.168.0.3: seq=0 ttl=64 time=0.542 ms
64 bytes from 192.168.0.3: seq=1 ttl=64 time=0.547 ms
64 bytes from 192.168.0.3: seq=2 ttl=64 time=0.543 ms
64 bytes from 192.168.0.3: seq=3 ttl=64 time=0.550 ms
64 bytes from 192.168.0.3: seq=4 ttl=64 time=0.578 ms
64 bytes from 192.168.0.3: seq=5 ttl=64 time=0.522 ms
64 bytes from 192.168.0.3: seq=6 ttl=64 time=0.474 ms
64 bytes from 192.168.0.3: seq=7 ttl=64 time=0.560 ms
64 bytes from 192.168.0.3: seq=8 ttl=64 time=0.535 ms
64 bytes from 192.168.0.3: seq=9 ttl=64 time=0.540 ms
64 bytes from 192.168.0.3: seq=10 ttl=64 time=0.527 ms
64 bytes from 192.168.0.3: seq=11 ttl=64 time=0.574 ms
64 bytes from 192.168.0.3: seq=12 ttl=64 time=0.520 ms
64 bytes from 192.168.0.3: seq=13 ttl=64 time=0.540 ms
64 bytes from 192.168.0.3: seq=14 ttl=64 time=0.579 ms
^C
--- 192.168.0.3 ping statistics ---
15 packets transmitted, 15 packets received, 0% packet loss
round-trip min/avg/max = 0.474/0.542/0.579 ms
root@bootloader#
dm9000ae在QT6410开发板上已经完美支持