凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 1125422
  • 博文数量: 146
  • 博客积分: 190
  • 博客等级: 入伍新兵
  • 技术积分: 5225
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-06 08:24
个人简介

慢行者

文章分类

全部博文(146)

文章存档

2013年(145)

2012年(1)

相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: linux

2013-05-10 16:16:42

linux驱动子系统之i2c(4) -凯发app官方网站

4.1 概述

i2c总线驱动是i2c适配器的软件实现,提供i2c适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和master_xfer的实现函数。

i2c总线驱动由i2c_adapter和i2c_algorithm来描述


4.2 s3c2440i2c控制器的硬件描述

s3c2440处理器内部集成了一个i2c控制器,通过四个寄存器来进行控制:

iiccon     i2c控制寄存器

iicstat     i2c状态寄存器

iicds       i2c收发数据移位寄存器

iicadd     i2c地址寄存器

通过iiccon,iicds,iicadd寄存器操作,可在i2c总线上产生开始位、停止位、数据和地址,而传输的状态则通过iicstat寄存器来获取。


4.3 i2c-s3c2410总线驱动分析(platform_driver)

i2c总线驱动代码在drivers/i2c/busses/i2c-s3c2410.c,这个代码同样支持s3c2410,s3c6410,s5pc110等samsung 系列的芯片。


初始化模块和卸载模块


[cpp]
  1. staticint __init i2c_adap_s3c_init(void
  2.          returnplatform_driver_register(&s3c24xx_i2c_driver); 
  3.   
  4. staticvoid __exit i2c_adap_s3c_exit(void
  5.          platform_driver_unregister(&s3c24xx_i2c_driver); 



总线驱动是基于platform来实现的,很符合设备驱动模型的思想。


[cpp]
  1. staticstruct platform_drivers3c24xx_i2c_driver = { 
  2.          .probe                = s3c24xx_i2c_probe, 
  3.          .remove            = s3c24xx_i2c_remove, 
  4.          .id_table  = s3c24xx_driver_ids, 
  5.          .driver                = { 
  6.                    .owner     = this_module, 
  7.                    .name       = "s3c-i2c"
  8.                    .pm  = s3c24xx_dev_pm_ops, 
  9.                    .of_match_table= s3c24xx_i2c_match, 
  10.          }, 
  11. }; 



s3c24xx_i2c_probe函数

当调用platform_driver_register函数注册platform_driver结构体时,如果platformdevice 和 platform driver匹配成功后,会调用probe函数,来初始化适配器硬件。


[cpp]
  1. staticint s3c24xx_i2c_probe(structplatform_device *pdev) 
  2.          …… 
  3.          /*初始化适配器信息 */ 
  4.          strlcpy(i2c->adap.name,"s3c2410-i2c", sizeof(i2c->adap.name)); 
  5.          i2c->adap.owner   = this_module; 
  6.          i2c->adap.algo    = &s3c24xx_i2c_algorithm; 
  7.          i2c->adap.retries= 2; 
  8.          i2c->adap.class   = i2c_class_hwmon | i2c_class_spd; 
  9.          i2c->tx_setup     = 50; 
  10.   
  11.          /*初始化自旋锁和等待队列头 */ 
  12.          spin_lock_init(&i2c->lock); 
  13.          init_waitqueue_head(&i2c->wait); 
  14.   
  15.          /*映射寄存器 */ 
  16.          res= platform_get_resource(pdev, ioresource_mem, 0); 
  17.          i2c->ioarea= request_mem_region(res->start, resource_size(res), 
  18.                                                 pdev->name); 
  19.          i2c->regs= ioremap(res->start, resource_size(res)); 
  20.   
  21.          /*设置i2c核心需要的信息 */ 
  22.          i2c->adap.algo_data= i2c; 
  23.          i2c->adap.dev.parent= &pdev->dev; 
  24.   
  25.          /*初始化i2c控制器 */ 
  26.          ret= s3c24xx_i2c_init(i2c); 
  27.   
  28.          /*申请中断 */ 
  29.          i2c->irq= ret = platform_get_irq(pdev, 0); 
  30.          ret= request_irq(i2c->irq, s3c24xx_i2c_irq, 0, 
  31.                               dev_name(&pdev->dev), i2c); 
  32.   
  33.    /* 注册i2c适配器 */ 
  34.          ret= i2c_add_numbered_adapter(&i2c->adap); 
  35.          …… 



probe主要工作是时能硬件并申请i2c适配器使用的io地址,中断号等,然后向i2c核心添加这个适配器。i2c_adapter注册过程i2c_add_numbered_adapter->i2c_register_adapter


i2c总线通信方法


[cpp]
  1. staticconststruct i2c_algorithms3c24xx_i2c_algorithm = { 
  2.          .master_xfer             = s3c24xx_i2c_xfer, 
  3.          .functionality             = s3c24xx_i2c_func, 
  4. }; 



s3c24xx_i2c_xfer函数是总线通信方式的具体实现,依赖于s3c24xx_i2c_doxfer和s3c24xx_i2c_message_start两个函数;


[cpp]
  1. staticint s3c24xx_i2c_doxfer(structs3c24xx_i2c *i2c, 
  2.                                   struct i2c_msg *msgs, int num) 
  3.          ret =s3c24xx_i2c_set_master(i2c); 
  4.   
  5.          i2c->msg     = msgs; 
  6.          i2c->msg_num= num; 
  7.          i2c->msg_ptr= 0; 
  8.          i2c->msg_idx= 0; 
  9.          i2c->state   = state_start; 
  10.   
  11.          s3c24xx_i2c_message_start(i2c,msgs); 



首先设置s3c i2c设备器为主设备,然后调用s3c24xx_i2c_message_start函数启动i2c消息传输。

s3c24xx_i2c_func函数返回适配器所支持的通信功能。


4.4 适配器的设备资源(platform_device)

s3c2440的i2c总线驱动是基于platform来实现,前面我们分析了platformdriver部分,再来看下platform device部分。

在arch/arm/plat-samsung/dev-i2c0.c文件中定义了platform_device结构体以及i2c控制器的资源信息:


[cpp]
  1. staticstruct resource s3c_i2c_resource[] ={ 
  2.          [0]= { 
  3.                    .start= s3c_pa_iic, 
  4.                    .end   = s3c_pa_iic sz_4k - 1, 
  5.                    .flags= ioresource_mem, 
  6.          }, 
  7.          [1]= { 
  8.                    .start= irq_iic, 
  9.                   .end  = irq_iic, 
  10.                    .flags= ioresource_irq, 
  11.          }, 
  12. }; 
  13.   
  14. struct platform_device s3c_device_i2c0 = { 
  15.          .name                 = "s3c2410-i2c",   /* 设备名 */ 
  16. #ifdef config_s3c_dev_i2c1 
  17.          .id               = 0, 
  18. #else 
  19.          .id               = -1, 
  20. #endif 
  21.          .num_resources         =array_size(s3c_i2c_resource), 
  22.          .resource   =s3c_i2c_resource, 
  23. }; 
  24.   
  25. struct s3c2410_platform_i2cdefault_i2c_data __initdata = { 
  26.          .flags                  = 0, 
  27.          .slave_addr      = 0x10,  /* i2c适配器的地址 */ 
  28.          .frequency        = 100*1000,  /* 总线频率 */ 
  29.          .sda_delay        = 100,   /* sda边沿延迟时间ns */ 
  30. }; 
  31.   
  32. void __init s3c_i2c0_set_platdata(structs3c2410_platform_i2c *pd) 
  33.          structs3c2410_platform_i2c *npd; 
  34.   
  35.          if(!pd) 
  36.                    pd= &default_i2c_data; 
  37.   
  38.          npd= s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), 
  39.                                    &s3c_device_i2c0); 
  40.   
  41.          if(!npd->cfg_gpio) 
  42.                    npd->cfg_gpio= s3c_i2c0_cfg_gpio; 



在板文件中把platform_device注册进内核:


[cpp]
  1. staticstruct platform_device*mini2440_devices[] __initdata = { 
  2.          …… 
  3.          &s3c_device_i2c0, 
  4. …… 
  5. }; 



调用s3c_i2c0_set_platdata 函数把适配器具体的数据赋值给dev.platform_data:


[cpp]
  1. staticvoid __init mini2440_init(void
  2.          …… 
  3. s3c_i2c0_set_platdata(null); 



i2c总线驱动就分析到这里。

阅读(2824) | 评论(0) | 转发(3) |
0

上一篇:

下一篇:linux驱动子系统之i2c(5)

给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图