S3C2440驱动简析——I2C驱动(4)

    说时迟,那时快,马上进入I2C驱动的最后一个小节了,在这个小节里,我们主要探讨i2c_algorithm 数据结构和i2c-core.c 的一些主要函数及其作用。有鉴于i2c-core.c 代码达2000行,所以本文仅对导出的函数(EXPORT_SYMBOL)进行简单注释,其它函数想必也是为前者服务的啦。好,马上进入正题:

 

i2c_algorithm 结构体

 

一个 i2c 适配器上的i2c 总线通信方法由其驱动程序提供的i2c_algorithm 数据结构描述,由algo 指针指向。i2c_algorithm 数据结构即为i2c_adapter 数据结构与具体i2c 适配器的总线通信方法的中间层,正是这个中间层使得上层的i2c 框架代码与与具体i2c 适配器的总线通信方法无关,从而实现了i2c 框架的
可移植性和重用性。当安装具体i2c 适配器的驱动程序时由相应驱动程序实现具体的i2c_algorithm 数据结构,其中的函数指针指向操作具体i2c 适配器的代码。

 

master_xfer/smbus_xfer 指针指向i2c 适配器驱动程序模块实现的i2c 通信协议或者smbus 通信协议。在用户进程通过i2c-dev 提供的/dev/i2c/%d 设备节点访问i2c 设备时,最终是通过调用
master_xfer 或者smbus_xfer 指向的方法完成的。

 

 

i2c-core.c

i2c.h 和i2c-core.c 为i2c 框架的主体,提供了核心数据结构的定义、i2c 适配器驱动和设备驱
动的注册、注销管理,i2c 通信方法上层的、与具体适配器无关的代码、检测设备地址的上层代码等;
i2c-dev.c 用于创建i2c 适配器的/dev/i2c/%d 设备节点,提供i2c 设备访问方法等。

 

下面介绍其主要的函数

函数i2c_init

主要做了以下几件事情:

1.i2c_add_driver(&dummy_driver);
   注册i2c总线

2.class_compat_register("i2c-adapter");

   注册一个可兼容的类

3.i2c_add_driver(&dummy_driver);
   加载驱动

 

函数i2c_exit

这个就不解释了呀~~

 

结构体i2c_bus_type

 

本结构体被导出,其里面包含了6个函数,其作用看名字就能猜到个大概。下面贴出以上6个函数的代码。

 

函数i2c_add_adapter

函数主要作用是添加一个适配器

1.idr_get_new_above(&i2c_adapter_idr, adapter,
                               __i2c_first_dynamic_bus_num, &id);

   确认是否还能分配得到适配器id,该操作不能被打断。

2.i2c_register_adapter(adapter);
   注册一个适配器

 

函数i2c_del_adapter

对应于i2c_add_adapter,此函数删除一个适配器。

 

函数 i2c_register_driver

 

注册一个设备

1.driver_register(&driver->driver);
   开始先注册一个设备

2.bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
   调用相对应的__attach_adapter 函数,并传递参数driver 给它。完成设备绑定适配器的动作。至于__attach_adapter 的代码粘贴如下

  

  

函数i2c_del_driver

相对应i2c_register_driver,本函数执行卸载设备的动作。

1.bus_for_each_dev(&i2c_bus_type, NULL, driver, __detach_adapter);
   调用__detach_adapter 函数,并传递函数driver 给它,完成分离设备和适配器的功能。

2.driver_unregister(&driver->driver);
   卸载设备。

   __detach_adapter 代码如下

  

 

最后来看3个重要的i2c总线操作函数

函数 i2c_transfer

该函数几乎与 i2c_master_recv 和i2c_master_send (接下来马上叙述)函数一模一样,都是在持有i2c_adapter 的lock 信号量的情况下利用i2c 适配器的algo 所指的i2c_algorithm 数据结构的master_xfer 方法执行实际的i2c 操作。

整个函数最重要的,当数for 循环里面的内容,而for 循环里面的内容,最最重要的,肯定就是

ret = adap->algo->master_xfer(adap, msgs, num);  经过前文提及的内容,master_xfer用于产生I2C访问周期需要的信号,以I2C消息为单位。

 

函数 i2c_master_send

把需要发送的数据以及其信息保存到msg 结构体,通过i2c_transfer 函数发送。

 

函数 i2c_master_recv

跟发送函数i2c_master_send 对应的一个接收函数,具体不作解释啦。

 

由于篇幅问题,故不能肆意展开全部代码,但我还是在这里罗列一下关于smbus协议需要注意的函数:

s32 i2c_smbus_read_byte(struct i2c_client *client);

s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);

s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);

s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value);

s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);

s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value);

s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
                                              u8 *values);

s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
                                              u8 length, const u8 *values);

static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                                   unsigned short flags,
                                                   char read_write, u8 command, int size,
                                                   union i2c_smbus_data * data);

以上一系列的函数,都是在i2c_smbus_xfer 函数的基础上建立起来的,只要理解了基石,其上的函数就不足为惧了。最后的最后,看一下这个藏在代码最后的基石吧!

 

函数 i2c_smbus_xfer

该函数通过适配器驱动提供的总线访问方法(i2c_algorithm 的smbus_xfer 方法)尝试访问处于addr 地址上的设备。其实函数里面最核心的一句是:

res = adapter->algo->smbus_xfer(adapter, addr, flags,
                                                read_write, command,
                                                protocol, data);

哈哈,这岂不妙哉,到最后我们还是回到结构体i2c_algorithm 的smbus_xfef 成员函数(见本文起始部分)。真是众里寻他千百度,蓦然回首,此函数却在灯火阑珊处。

 

 

经过这一个i2c系列4个小节的学习,自己对代码的分析,特别是驱动代码的分析有了一定的提高,起码在心理上不会感到畏惧。希望各位初学的朋友能够跟我一起坚持下去,踏踏实实地走好每一步!

 

 

本系列博文链接:

I2C驱动(1)http://blog.csdn.net/jarvis_xian/archive/2011/05/27/6449939.aspx
I2C驱动(2)http://blog.csdn.net/jarvis_xian/archive/2011/05/27/6451168.aspx
I2C驱动(3)http://blog.csdn.net/jarvis_xian/archive/2011/05/28/6452431.aspx
I2C驱动(4)http://blog.csdn.net/jarvis_xian/archive/2011/05/30/6455697.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章