ARM-Linux s3c2440 之UART分析(五)

本文深入分析了ARM-Linux系统中s3c2440的UART实现,从硬件平台初始化、串口驱动结构到platform_device的详细配置,阐述了串口作为platform device的各个层面,包括smdk2440_map_io()、s3c24xx_init_uarts()等关键函数的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.youkuaiyun.com/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;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值