Linux驱动子系统之I2C(5)

5 客户驱动

5.1 概述

I2C客户驱动是对I2C从设备的实现,一个具体的I2C客户驱动包括两个部分:一部分是i2c_driver,用于将设备挂接于i2c总线;另一部分是设备本身的驱动。

I2C客户驱动程序主要由i2c_driver和i2c_client来描述。

 

5.2 实例源码分析

好了,我们来深入了解客户驱动代码的实现,drivers/misc/eeprom/at24.c文件支持大多数I2C接口的eeprom

I2c_driver实现

[cpp]  view plain copy
  1. static struct i2c_driver at24_driver = {  
  2.          .driver= {  
  3.                    .name= "at24",  
  4.                    .owner= THIS_MODULE,  
  5.          },  
  6.          .probe= at24_probe,  /* 当i2c_client和i2c_driver匹配时调用 */  
  7.          .remove= __devexit_p(at24_remove), /* 注销时调用 */  
  8.          .id_table= at24_ids,   /* i2c_driver支持的i2c_client类型 */  
  9. };  

初始化和卸载

[cpp]  view plain copy
  1. static int __init at24_init(void)  
  2. {  
  3.          returni2c_add_driver(&at24_driver);  
  4. }  
  5.    
  6. static void __exit at24_exit(void)  
  7. {  
  8.          i2c_del_driver(&at24_driver);  
  9. }  

At24_Probe函数

[cpp]  view plain copy
  1. static int at24_probe(struct i2c_client*client, const struct i2c_device_id *id)  
  2. {  
  3.          ……  
  4.           
  5.          /* 
  6.           * Export the EEPROM bytes through sysfs, sincethat's convenient. 
  7.           * By default, only root should see the data(maybe passwords etc) 
  8.           */  
  9.          sysfs_bin_attr_init(&at24->bin);  
  10.          at24->bin.attr.name= "eeprom";  
  11.          at24->bin.attr.mode= chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;  
  12.          at24->bin.read= at24_bin_read;  
  13.          at24->bin.size= chip.byte_len;  
  14.    
  15.          at24->macc.read= at24_macc_read;  
  16.         writable = !(chip.flags &AT24_FLAG_READONLY);  
  17.          if(writable) {  
  18.                    if(!use_smbus || i2c_check_functionality(client->adapter,  
  19.                                      I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)){  
  20.    
  21.                             unsignedwrite_max = chip.page_size;  
  22.    
  23.                             at24->macc.write= at24_macc_write;  
  24.    
  25.                             at24->bin.write= at24_bin_write;  
  26.                             at24->bin.attr.mode|= S_IWUSR;  
  27.                             ……  
  28.          }  
  29. ……  
  30.           
  31. err = sysfs_create_bin_file(&client->dev.kobj,&at24->bin);  
  32.          if(err)  
  33.                    gotoerr_clients;  
  34.    
  35.          i2c_set_clientdata(client,at24);  
  36.          ……  
  37. }  

Probe函数主要的工作是在sys目录下创建bin节点文件,用户可以同此节点文件来操作eeprom,并提供操作方法(read,write)

 

5.3  I2c_client实现

At24c不依赖于具体的CPU和I2C控制器硬件特性,因此如果电路板包含该外设,只需要添加对应的i2c_board_info,下面是at24c08 i2c_client在板文件中的实现:

[cpp]  view plain copy
  1. static struct at24_platform_data at24c08 ={  
  2.          .byte_len = SZ_8K / 8,   /* eeprom的存储大小,单位Byte */  
  3.          .page_size        = 16,      /* 页大小 Byte */  
  4. };  
  5.    
  6. static struct i2c_board_infomini2440_i2c_devs[] __initdata = {  
  7.          {  
  8.                    I2C_BOARD_INFO("24c08",0x50),          /* 24c08设备名,0x50设备地址 */  
  9.                    .platform_data= &at24c08,              /* 赋值给client->dev->platform_data */  
  10.          },  
  11. };  
  12. static void __init mini2440_init(void)  
  13. {  
  14.          ……  
  15.          i2c_register_board_info(0,mini2440_i2c_devs,    /* busnum = 0,busnum是适配器编号,用来识别从设备使用的哪个适配器 */  
  16.                                      ARRAY_SIZE(mini2440_i2c_devs));  
  17.          ……  
  18. }  

I2c_register_board_info函数会把I2C从设备硬件特性信息注册到全局链表__i2c_board_list,在调用i2c_add_adapter函数时,会遍历__i2c_board_list获得从设备信息来构造i2c_client。

 

I2c_client的构建

我们调用I2c_register_board_info函数会把I2C从设备硬件特性信息注册到全局链表__i2c_board_list,但是还没有构建出一个i2c_client结构体,也没有注册进I2C总线。我们来分析一下构造的过程,调用i2c_add_adapter函数时,会遍历__i2c_board_list获得从设备信息来构造i2c_client:i2c_register_adapter()->i2c_scan_static_board_info()->i2c_new_device()->device_register()。

 

5.4  I2c_driver和i2c_client的match

在调用i2c_add_driver注册i2c_driver和构建i2c_client时,都会调用i2c bus中注册的i2c_device_match()->i2c_match_id()函数通过i2c_driver->id_table->name和client->name来匹配

[cpp]  view plain copy
  1. static const struct i2c_device_id*i2c_match_id(const struct i2c_device_id *id,  
  2.                                                         conststruct i2c_client *client)  
  3. {  
  4.          while(id->name[0]) {  
  5.                    if(strcmp(client->name, id->name) == 0)  
  6.                             returnid;  
  7.                    id++;  
  8.          }  
  9.          returnNULL;  
  10. }  

5.5 测试

已在mini2440上实验成功,在/sys/bus/i2c/devices/0-0050/目录下(50代表从设备地址)会产生一个eeprom文件,这个文件相当于是硬件设备eeprom的映射,我们可以像普通文件一样对eeprom文件进行操作,实质上就是就硬件eeprom的操作。重启开发板,你会发现对eeprom文件修改过的内容不会改变,这就证明实验成功了,要知道sys文件系统是无法对数据保存的。


原文见:http://blog.csdn.net/paul_liao/article/details/6997854

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值