您的位置:首页 > 运维架构 > Linux

ARM-Linux s3c2440 之UART分析(五)

2012-01-16 14:23 183 查看
====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.csdn.net/yyplc====

从上面四篇介绍文章中,已经清楚了串口设备与串口驱动实现的各层次关系流程。是一种从上而下的关系,从第二篇的层次流程图中可以看出。之前说过串口设备是一种platform device,下面看看串口作为platform device的实现细节。

串口的硬件平台实现smdk2440_map_io()初始化入口:

static void __init smdk2440_map_io(void)
{
       s3c24xx_init_io(smdk2440_iodesc,ARRAY_SIZE(smdk2440_iodesc));
       s3c24xx_init_clocks(12000000);
       s3c24xx_init_uarts(smdk2440_uartcfgs,ARRAY_SIZE(smdk2440_uartcfgs));  //串口初始化
}


s3c24xx_init_uarts()初始化串口, 主要完成platform device结构相关参数的赋值,如IO,中断,以及platform device私有数据赋值等。

串口platform_device结构:

static struct platform_device s3c24xx_uart_device0= {
       .id           = 0,   // ID号
};
 
static struct platform_devices3c24xx_uart_device1 = {
       .id           = 1,
};
 
static struct platform_devices3c24xx_uart_device2 = {
       .id           = 2,
};


要完成platform_device参数初始化,主要涉及到一下数据结构:

串口配置数据结构:

static struct s3c2410_uartcfgtq2440_uartcfgs[] __initdata = {
       [0]= {
              .hwport        =0,
              .flags          = 0,
              .ucon          = 0x3c5,  // rx,tx采用中断方式
              .ulcon         = 0x03,   //数据长度设置为8-bits
              .ufcon         = 0x51,   //开启FIFO,并设置rx,tx触发字节数
       },
       [1]= {
              .hwport        =1,
              .flags          = 0,
              .ucon          = 0x3c5, 
              .ulcon         = 0x03,            
.ufcon          = 0x51,  
       },
       [2]= {
              .hwport        =2,
              .flags          = 0,
              .ucon          = 0x3c5,
              .ulcon         = 0x03,
              .ufcon         = 0x51,
       }
};


串口资源:

static struct resources3c2410_uart0_resource[] = {
       [0]= {
              .start= S3C2410_PA_UART0,
              .end   = S3C2410_PA_UART0 + 0x3fff,  
              .flags= IORESOURCE_MEM,       
       },
       [1]= {
              .start= IRQ_S3CUART_RX0,
              .end   = IRQ_S3CUART_ERR0,
              .flags= IORESOURCE_IRQ,
       }
};
 
struct s3c24xx_uart_resourcess3c2410_uart_resources[] __initdata = {
       [0]= {
              .resources      = s3c2410_uart0_resource,
              .nr_resources  = ARRAY_SIZE(s3c2410_uart0_resource),
       },
       [1]= {
              .resources      = s3c2410_uart1_resource,
              .nr_resources  = ARRAY_SIZE(s3c2410_uart1_resource),
       },
       [2]= {
              .resources      = s3c2410_uart2_resource,
              .nr_resources  = ARRAY_SIZE(s3c2410_uart2_resource),
       },
       [3]= {
              .resources      = s3c2410_uart3_resource,
              .nr_resources  = ARRAY_SIZE(s3c2410_uart3_resource),
       },
};


最后通过函数s3c24xx_init_uartdevs()完成 串口platform_device的初始化:

void __init s3c24xx_init_uartdevs(char*name,
                              struct s3c24xx_uart_resources *res,
                              struct s3c2410_uartcfg *cfg, int no)
{//name = s3c2440-uart, res =s3c2410_uart_resources[], cfg = tq2440_uartcfgs, no = 3
       structplatform_device *platdev;
       structs3c2410_uartcfg *cfgptr = uart_cfgs;
       structs3c24xx_uart_resources *resp;
       intuart;
 
       memcpy(cfgptr,cfg, sizeof(struct s3c2410_uartcfg) * no);
 
       for(uart = 0; uart < no; uart++, cfg++, cfgptr++) {
              platdev= s3c24xx_uart_src[cfgptr->hwport];  //platdev = s3c24xx_uart_device0
 
              resp= res + cfgptr->hwport;  //resp =s3c2410_uart_resources[] + tq2440_uartcfgs.hwport
 
              s3c24xx_uart_devs[uart]= platdev; //
 
              platdev->name= name;
              platdev->resource= resp->resources;
              platdev->num_resources= resp->nr_resources;
 
              platdev->dev.platform_data= cfgptr;//plat_form_data = cfgptr = tq2440_uartcfgs
       }
 
       nr_uarts= no;
}


最终在platform_add_device()中完成注册

platform_add_devices(s3c24xx_uart_devs,nr_uarts);
int platform_add_devices(structplatform_device **devs, int num)
{
       inti, ret = 0;
 
       for(i = 0; i < num; i++) {
              ret= platform_device_register(devs[i]);
              if(ret) {
                     while(--i >= 0)
                            platform_device_unregister(devs[i]);
                     break;
              }
       }
 
       return ret;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: