移植Linux-2.6.22到GQ2440上

来源:互联网 发布:软件开发 等级 编辑:程序博客网 时间:2024/05/22 06:08

移植 linux-2.6.22

1 解压
  find -name "*defconfig"
  修改顶层 Makefile
  ARCH            ?= arm
 CROSS_COMPILE   ?= arm-linux-
  make s3c2410_defconfig
  make menuconfig
  make uImage
  tftp 下载到sdram 运行,乱码
2 修改代码
   MACHINE_START(S3C2440, "SMDK2440")
    /* Maintainer: Ben Dooks <ben@fluff.org> */
    .phys_io = S3C2410_PA_UART,
    .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params = S3C2410_SDRAM_PA + 0x100,
   
    .init_irq = s3c24xx_init_irq,
    .map_io  = smdk2440_map_io,
    .init_machine = smdk2440_machine_init,
    .timer  = &s3c24xx_timer,
   MACHINE_END
  指针函数 smdk2440_map_io 中设置的晶振频率 和 开发板的不一致,改为12000000
 
  /*修改分区*/
  static struct mtd_partition smdk_default_nand_part[] = {
   [0] = {
    .name = "u-boot",
    .offset = 0,
    .size = SZ_256K,
   },
   [1] = {
    .name = "params",
    .offset = MTDPART_OFS_APPEND,
    .size = SZ_128K,
   },
   [2] = {
    .name = "kernel",
    .offset = MTDPART_OFS_APPEND,
    .size = SZ_2M,
   },
   [3] = {
    .name = "rootfs",
    .offset = MTDPART_OFS_APPEND,
    .size = MTDPART_SIZ_FULL,
   }
  };
    make uImage
3 把yaffs文件系统加到系统中
    cd yaffs2-662466a/
    ./patch-ker.sh  c m linux-tree
    把yaffs 源文件 复制到 linux-tree/fs/yaffs 中
    make menuconfig
    在file system中把yaffs 支持选上
    make uImage
    一次能过。不用像3.4.2那样,需要修改一些代码
    现在生成的uImage内核文件就可以正常启动yaffs2挂载根文件系统了
    但是系统在启动时会出现下面的错误
4 修改代码,去掉如下错误,使内核支持USB
   usb 1-1: device descriptor read/64, error -62
   usb 1-1: new full speed USB device using s3c2410-ohci and address 3
   usb 1-1: device descriptor read/64, error -62
   usb 1-1: device descriptor read/64, error -62
   usb 1-1: new full speed USB device using s3c2410-ohci and address 4
   usb 1-1: device not accepting address 4, error -62
   usb 1-1: new full speed USB device using s3c2410-ohci and address 5
   usb 1-1: device not accepting address 5, error -62
   
   查找错误信息的出现地方:
   linux-2.6.22\drivers\usb\core\hub.c下的 hub_port_init 函数中
     if (r) {
      dev_err(&udev->dev, "device descriptor "
        "read/%s, error %d\n",
        "64", r);
      retval = -EMSGSIZE;
      continue;
     }
      错误码为:-62,那么查找错误码的宏定义出现的地方
      发现在include/asm-generic/errno.h中定义了:
      #define ETIME 62 /*timer expired*/  timeout 超时了
      由于错误出现在 hub_port_init 初始化中的:
        r = usb_control_msg(udev, usb_rcvaddr0pipe(),
     USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
     USB_DT_DEVICE << 8, 0,
     buf, GET_DESCRIPTOR_BUFSIZE,
     USB_CTRL_GET_TIMEOUT); 的这个函数获取usb设备信息的时候产生了超时
   google、baidu 得出的结果是:
   确定问题就在ohci-s3c2410.c中的 s3c2410_start_hc
   USB的时钟设置不正确或没有设置,导致USB Host的48MHz时钟没有跑起来
   关于USB时钟设置可以参考芯片说明书
   修改代码:  
     static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
     {
      struct s3c2410_hcd_info *info = dev->dev.platform_data;
      /*在网上还找到一种说法*/
      unsigned long upllvalue = (0x78<<12) | (0x02<<4) | (0x03);
      while(upllvalue!=__raw_readl(S3C2410_UPLLCON) )
      {
       __raw_writel(upllvalue,S3C2410_UPLLCON);
       mdelay(1);
      }
      dev_dbg(&dev->dev, "s3c2410_start_hc:\n");//这句是原来就有的
      /**/
      /*modify here*/
      /*
      unsigned long upllvalue =  (0x38<<12)|(0x02<<4)|(0x01);
      unsigned long upllvalue1 = (0x38<<12)|(0x02<<4)|(0x02);//
      dev_dbg(&dev->dev, "s3c2410_start_hc:\n");//这句是原来就有的
      __raw_writel(upllvalue,S3C2410_UPLLCON);
            mdelay(20);
            __raw_writel(upllvalue1,S3C2410_UPLLCON);
            mdelay(20);//
      */
     
      clk_enable(usb_clk);
      mdelay(2);   /* let the bus clock stabilise */
     
      clk_enable(clk);
     
      if (info != NULL) {
       info->hcd = hcd;
       info->report_oc = s3c2410_hcd_oc;
     
       if (info->enable_oc != NULL) {
        (info->enable_oc)(info, 1);
       }
      }
     }
5 修改配置选项,使内核支持U盘
    挂载U盘:mount /dev/uba /mnt
6 修改,使支持网卡
  ifconfig eth0 down出现如下错误
    ifconfig: SIOCGIFFLAGS: No such device
    估计是网卡驱动的事,查看make menuconfig,发现dm9000也配置上了
    google baidu搜索下,发现是网卡驱动没有运行。
    修改网卡驱动代码:
  a 修改linux-2.6.22/arch/arm/plat-s3c24xx/devs.c
    加入:
    /*加入DM9000网卡支持*/
    #include <linux/dm9000.h>
    #include <linux/ioport.h>
    #define DM9000_BASE 0x20000000  //网卡的基地址,根据板子上DM9000网卡接的位置,我的接到nSGN4上,地址为20000000
    static struct resource s3c_dm9000_resource[] ={
     [0] = {
      .start = DM9000_BASE,
      .end   =  DM9000_BASE +0x03 ,
      .flags =  IORESOURCE_MEM,
     },
     [1] = {
      .start = DM9000_BASE + 0x4,
      .end   =  DM9000_BASE + 0x4 +0x3 ,
      .flags =  IORESOURCE_MEM,
     },
     [2] = {
      .start = IRQ_EINT7,//网卡的外部中断接到了CPU的EINT7上
      .end   = IRQ_EINT7,
      .flags =  IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,//后面的IORESOURCE_IRQ_HIGHEDGE最好加上,否则会出现还是
     }                                                  //出现 ifconfig: SIOCGIFFLAGS: No such device
    };
    
    static struct dm9000_plat_data s3c_device_dm9000_platdata = {
     .flags = DM9000_PLATF_16BITONLY,
    };
    //平台驱动
    struct platform_device s3c_device_dm9000 = {
     .name = "dm9000",
     .id      = -1,  //也可以是0,有待考证
     .num_resources = ARRAY_SIZE(s3c_dm9000_resource),
     .resource   = s3c_dm9000_resource,
     .dev ={
       .platform_data = &s3c_device_dm9000_platdata,
      }
    };
    EXPORT_SYMBOL(s3c_device_dm9000);
    /*导出设置*/
  b 修改 linux-2.6.22/include/asm-arm/plat-s3c24xx/devs.h 加入:
     /*修改加入一行代码*/
   extern struct platform_device s3c_device_dm9000;  
  c 修改 linux-2.6.22/arch/arm/mach-s3c2440/mach-smdk2440.c
    static struct map_desc smdk2440_iodesc[] __initdata = {   中加入一个元素
       { /*这里加入DM9000的地址映射*/
     .virtual = S3C2410_ADDR(0x02100300),
     .pfn  = __phys_to_pfn(0x20000300),
     .length  = SZ_1M,
     .type  = MT_DEVICE,  
    }
   再修改:
   static struct platform_device *smdk2440_devices[] __initdata = {  中加入一个元素
     /*修改加入一行代码*/
    &s3c_device_dm9000,
 d 修改 linux-2.6.22/drivers/net/dm9000.c
   加入:
     /*加入几个头文件*/
    #include <asm-arm/arch/irqs.h>
    #include <asm-arm/arch/hardware.h>
    #include <asm-arm/arch/regs-gpio.h>
    #include <linux/irq.h>
    #include <asm/arch-s3c2410/map.h>
    #include <asm/arch-s3c2410/regs-mem.h>
    #include <asm/arch-s3c2410/irqs.h>
    #include <asm/arch-s3c2410/hardware.h>
    #include <asm/arch-s3c2410/regs-gpio.h>
  修改 static int dm9000_probe(struct platform_device *pdev) 加入:
     //******************************tekkaman********************************
     unsigned int value;
    static int once=0;
         if (once) {
          return -ENXIO;
    }
    //tekkaman
    value = __raw_readl(S3C2410_BWSCON);
    value &= ~(S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_32);
    value |= (S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_16);
    __raw_writel(value, S3C2410_BWSCON);
    value=0;
    value = (S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|
         S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|
         S3C2410_BANKCON_PMCnorm);
    __raw_writel(value,S3C2410_BANKCON4);
    set_irq_type(IRQ_EINT7,IRQ_TYPE_LEVEL_HIGH );
    s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_EINT7);
    s3c2410_gpio_pullup(S3C2410_GPF7, 0);
    //以上代码完成对网卡所用到的寄存器,中断与中断方式的设置,probe函数在发现网卡时就会自动运行
    //******************************tekkaman********************************
  可以在 dm9000_init_dm9000() 函数中写死网卡MAC地址的,这里没有写死:
  而是使用uboot传入的网卡地址,方法:
    unsigned char ne_def_eth_mac_addr[]={0x08,0x08,0x1a,0x2b,0x3c,0x4f};
    int i;
    for(i=0;i<6;i++)
      dev->dev_addr[i] = ne_def_eth_mac_addr[i];
  以上这四行代码,在源码中被我注释掉了。
  到此,make menuconfig ,加入对DM9000支持,编译,发现能ifconfig eth0 192.168.0.2 up 了
  在调试的过程中,遇的问题:
   dm9000 Ethernet Driver
   dm9000: read wrong id 0x2b2a2928
   dm9000: read wrong id 0x2b2a0028
   dm9000: wrong id: 0x2b2a0028
   dm9000: not found (0).
  *********************************************************************************************** 
  *解决方法:.flags =  IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE 中加入:IORESOURCE_IRQ_HIGHEDGE *
  ***********************************************************************************************
  e 修改挂在NFS
    mount -t nfs -o nolock 192.168.0.1:/common/rootfs /mnt 后:
    mount: mounting 192.168.0.1:/common/rootfs on /mnt failed: Invalid argument
    ****************************************************************************
    百思不得其解,google baidu了一个下午和晚上:觉得两个方法,比较靠谱:
    1 重新配置linux :选上RPC服务,因为所有的NFS服务都需要这个RPC,所以把两个RPC相关的选项选中
    2 可能是mount命令不支持nfs操作指令,感觉很靠谱,Invalid argument(无效的参数) 对应-t nfs
      解决方法:重新配置busybox,make menuconfig
      Linux System Utilities  --->
          Support mounting NFS file systems on Linux < 2.6.23  选中该选项
      make;make install;重新安装到wds_rootfs根文件系统中,重新制作yaffs格式文件系统,烧写到flash 中
    重启系统,挂载ok.........
7 制作补丁
    diff -urN 原始目录树 修改过的目录树 > xxx.patch
   
    打补丁过程:
    cd 原始目录树
    patch -p1 ../xxx.patch

原创粉丝点击