Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6557
  • 博文数量: 1
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-23 20:16
文章分类
文章存档

2012年(1)

我的朋友
最近访客

分类:

2012-11-29 13:57:45

这几天移植在linux内核下调试16C554,扩展四串口驱动,用的是linux内核自带的8250.c驱动。
(1)8250.c内自带serial8250_init(),它在内核初始化时完成驱动的注册,所以我们需要添加的是设备资源。
(2)在arch/arm/mach-s3c2410/mach-smdk2410.c中添加四串口设备:
    static struct plat_serial8250_port my2410_st16c554_8250_data[] = {
      { //ARM体系结构中将IO和MEMORY统一编址,
     //因此这里使用的是Memory地址                   
        .mapbase = (unsigned long)S3C2410_CS1 + 0x0FC0,   
        .irq                = IRQ_EINT2,                 
        .uartclk          = 1843200,   
        .iotype           = UPIO_MEM32,        
        .flags             = (UPF_BOOT_AUTOCONF | UPF_IOREMAP),     
        .regshift         = 0,
        },
 //PORT(S3C2410_CS1 + 0x0, IRQ_EINT0),
       { //ARM体系结构中将IO和MEMORY统一编址,
     //因此这里使用的是Memory地址                   
        .mapbase = (unsigned long)S3C2410_CS1 + 0x0FA0,   
        .irq                = IRQ_EINT8,                 
        .uartclk          = 1843200,   
        .iotype           = UPIO_MEM32,        
        .flags             = (UPF_BOOT_AUTOCONF | UPF_IOREMAP),     
        .regshift         = 0,
         },
//PORT(S3C2410_CS2 + 0x0, IRQ_EINT1),
       { //ARM体系结构中将IO和MEMORY统一编址,
     //因此这里使用的是Memory地址                   
        .mapbase = (unsigned long)S3C2410_CS1 + 0x0F60,   
        .irq                = IRQ_EINT11,                 
        .uartclk          = 1843200,   
        .iotype           = UPIO_MEM32,        
        .flags             = (UPF_BOOT_AUTOCONF | UPF_IOREMAP),     
        .regshift         = 0,
         },
       //PORT(S3C2410_CS3 + 0x0, IRQ_EINT2),
         { //ARM体系结构中将IO和MEMORY统一编址,
     //因此这里使用的是Memory地址                   
        .mapbase = (unsigned long)S3C2410_CS1 + 0x0EE0,   
        .irq                = IRQ_EINT19,                 
        .uartclk          = 1843200,   
        .iotype           = UPIO_MEM32,        
        .flags             = (UPF_BOOT_AUTOCONF | UPF_IOREMAP),     
        .regshift         = 0,
         },
       //PORT(S3C2410_CS5 + 0x0, IRQ_EINT3),
       { },
};
 
static struct platform_device my2410_device_st16c554 = {
     .name             = "serial8250",
     .id                 = PLAT8250_DEV_PLATFORM,
     .dev               = {
            .platform_data       = &my2410_st16c554_8250_data,
     },
};
然后在smdk2410_devices中添加上面定义的设备。
static struct platform_device *smdk2410_devices[] __initdata = {
 &s3c_device_usb,
 &s3c_device_lcd,
 &s3c_device_wdt,
 &s3c_device_i2c,
 &s3c_device_iis,
      &s3c_device_nand,
      &my2410_device_st16c554,
}; 
(3)下面就要修改8250.c
    首先在serial8250_init()中,serial8250_isa_devs = platform_device_register_simple("serial8250",PLAT8250_DEV_PLATFORM, NULL, 0)这个函数有点诡异,我起先对它没有修改,但是内核启动之后设备总是注册不成功,找了找原因,实在不知道其中的PLAT8250_DEV_PLATFORM是什么意思,故把它改成-1,再次启动内核,貌似有了点进展。
    但是在内核启动的过程中,总是停止在serial8250_config_port()中autoconfig()中的serial_in()中,找到源代码查看,发现serial_in()中的readl()出了问题。readl()是访问内存空间虚拟地址的一个函数,在调用它之前必须将I/O空间映射到虚拟内存空间,所以估计是没有映射。
    找到:
static int serial8250_request_std_resource(struct uart_8250_port *up)
{
 unsigned int size = 8 << up->port.regshift;
 int ret = 0;
        printk("the port's size is %d",size);
 switch (up->port.iotype) {
 case UPIO_MEM:
  if (!up->port.mapbase)
   break;
  if (!request_mem_region(up->port.mapbase, size, "serial")) {
   ret = -EBUSY;
   break;
  }
  if (up->port.flags & UPF_IOREMAP) {
   up->port.membase = ioremap(up->port.mapbase, size);
   if (!up->port.membase) {
    release_mem_region(up->port.mapbase, size);
    ret = -ENOMEM;
   }
  }
  break;
 case UPIO_HUB6:
 case UPIO_PORT:
  if (!request_region(up->port.iobase, size, "serial"))
   ret = -EBUSY;
  break;
 }
 return ret;
}
 
发现里面的iotype没有我们想要的UPIO_MEM32,所以没有进行request_mem_region和ioremap,故将UPIO_MEM改为UPIO_MEM32。
   再次编译,启动,可以注册了,下一步就要进行测试。
阅读(791) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~