I2C驱动框架(二)
参考:I2C子系统之I2C bus初始化——I2C_init()
在linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的i2c_init()函数。
static int __init i2c_init(void)
{
retval = bus_register(&i2c_bus_type);
i2c_adapter_compat_class = class_compat_register("i2c-adapter");
retval = i2c_add_driver(&dummy_driver);
return ;
}
1.bus_register(&i2c_bus_type)注册i2c总线
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
该函数执行完会在/sys/bus目录下创建i2c子目录,并在i2c子目录下创建devices和drivers两个目录,以后注册到i2c总线上的设备和驱动会分别放在这两个目录。

2.class_compat_register("i2c-adapter")在/sys/class/目录下创建i2c-adapter子类目录

3.i2c_add_driver(&dummy_driver)在i2c-bus上注册驱动,该函数执行成功后会在/sys/bus/i2c/drivers目录下创建.driver.name = "dummy"为名字的目录。

static struct i2c_driver dummy_driver = {
.driver.name = "dummy",
.probe = dummy_probe,
.remove = dummy_remove,
.id_table = dummy_id,
};
分析该该函数前先看一下i2c_bus_type总线-设备-驱动模型。

struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)和
int i2c_add_adapter(struct i2c_adapter *adapter)向i2c_bus_type注册i2c_client和i2c_adapter。两种不同的设备以dev->type来区分,
struct device_type i2c_adapter_type = {
.groups = i2c_adapter_attr_groups,
.release = i2c_adapter_dev_release,
};
static struct device_type i2c_client_type = {
.groups = i2c_dev_attr_groups,
.uevent = i2c_device_uevent,
.release = i2c_client_dev_release,
};
static inline int i2c_add_driver(struct i2c_driver *driver)则向i2c_bus_type注册i2c_driver。
i2c_add_driver(&dummy_driver);
--> i2c_register_driver(THIS_MODULE, driver);
-->&dummy_driver->driver.bus = &i2c_bus_type;
-->res = driver_register(&(&dummy_driver)->driver);//将驱动注册到i2c_bust_type
-->i2c_for_each_dev(&dummy_driver, __process_new_driver);
//遍历i2c_bus_type总线上的设备
-->bus_for_each_dev(&i2c_bus_type, NULL, &dummy_driver, __process_new_driver);
//以找到的设备和dummy_driver为参数调用__process_new_driver函数
-->__process_new_driver(dev, &dummy_driver);
由于i2c_add_driver(&dummy_driver)执行时,i2c_bus_type总线上还没有注册设备,所以不会执行__process_new_driver函数。
但下面还是分析一下__process_new_driver函数的执行过程,该函数最终调用i2c_detect函数检测设备是否存在。
__process_new_driver(dev,&dummy_driver)
-->if (dev->type != &i2c_adapter_type) return ;//判断是i2c_adapter_type类型的设备才继续执行
--> i2c_do_add_adapter(&dummy_driver, to_i2c_adapter(dev));
-->i2c_detect(adap, &dummy_driver);// Detect supported devices on that bus, and instantiate them
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
-->int adap_id = i2c_adapter_id(adapter);//获取adapter的序列号,即处理器的第几个I2C控制器
-->const unsigned short *address_list = driver->address_list; //获取I2C从设备的地址数组
-->if (!(adapter->class & driver->class)) return ; //类型匹配后才继续执行
-->struct i2c_client *temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);//分配i2c_client结构体
-->temp_client->adapter = adapter;
-->for (i = ; address_list[i] != I2C_CLIENT_END; i += ) //遍历address_list里的i2c地址
-->temp_client->addr = address_list[i];//设置从地址到i2c_client结构体
-->i2c_detect_address(temp_client, driver);//检测该从地址对应的设备是否存在
static int i2c_detect_address(struct i2c_client *temp_client,struct i2c_driver *driver)
-->int addr = temp_client->addr;
-->i2c_check_addr_validity(addr);//检测地址有效性
-->i2c_check_addr_busy(adapter, addr);//检测设备是否正在使用,同一条物理I2Cbus上不能有两个相同address的器件
-->i2c_default_probe(adapter, addr);//检测i2c物理总线上是否有设备应答
-->struct i2c_board_info info.addr=temp_client->addr
-->driver->detect(temp_client, &info);//调用i2c_driver的detect函数检测设备,并经info.type赋值
-->struct i2c_client *client = i2c_new_device(adapter, &info);//在i2b_bus_type总线上创建i2c_client设备
-->list_add_tail(&client->detected, &driver->clients);//创建设备成功则将该i2c_client挂到i2c_driver的链表上
I2C驱动框架(二)的更多相关文章
- I2C驱动框架(四)
参考:I2C子系统之platform_driver初始化——I2C_adap_s3c_init() 在完成platform_device的添加之后,i2c子系统将进行platform_driver的注 ...
- I2C驱动框架 (kernel-3.4.2)
先用韦老师的图: 注: 新版本内核的i2c驱动框架采用了 i2c_client -------> i2c_bus_type <-------- i2c_driver 框架 如 ...
- I2C驱动框架(三)
参考:I2C子系统之platform_device初始化——smdk2440_machine_init() I2C驱动框架还应用了另一种总线-设备-驱动模型,平台设备总线platform_bus_ty ...
- I2C驱动框架(kernel-2.6.22.6)
以用i2c通信的实时时钟为例 框架入口源文件:i2c_m41t11.c (可根据入口源文件,再按着框架到内核走一遍) 内核版本:linux_2.6.22.6 硬件平台:JZ2440 以下是驱动框架 ...
- Linux 驱动框架---i2c驱动框架
i2c驱动在Linux通过一个周的学习后发现i2c总线的驱动框架还是和Linux整体的驱动框架是相同的,思想并不特殊比较复杂的内容如i2c核心的内容都是内核驱动框架实现完成的,今天我们暂时只分析驱动开 ...
- 【Linux高级驱动】I2C驱动框架分析
1.i2c-dev.c(i2c设备驱动组件层) 功能:1)给用户提供接口 i2c_dev_init //入口函数 /*申请主设备号*/ register_chrdev(I2C_MAJOR(), &q ...
- Linux I2C驱动框架
Linux的I2C体系结构分为3个组成部分: I2C核心( i2c-core.c ): I2C核心提供了I2C总线驱动和设备驱动的注册.注销方法.I2C通信方法("algorithm&qu ...
- I2C驱动框架(五)
参考:I2C子系统之 adapter driver注册——I2C_dev_init() i2c的操作在内核中是当做字符设备来操作的,相关初始化在由i2c_dev_init函数来初始化. static ...
- I2C驱动框架(一)
参考:I2C子系统之内核中I2C子系统的结构 结合vmlinux.lds和Makefile可确定i2c初始化函数的执行顺序如下: 1./dricer/i2c/i2c-core.c中的函数:i2c_in ...
随机推荐
- Codeforces 1139F(树状数组+扫描线)
题目传送 做法 对于每个人,inc为x,pref为y:对于每道菜,p和s为x,b为y 于是根据题意有\[p[i]<=x<=s[i]\]\[p[i]+b[i]<=x+y\]\[p[i] ...
- [LOJ#10042] 收集雪花
题目链接: 点我 题目分析: 双指针扫描可以保证在\(O(n)\)的时间复杂度内处理这道题.另外,虽然这个题标签是\(hash\),但是字符串\(hash\)是可以卡掉的,所以建议直接离散化. 维护两 ...
- JetSpeed2因dom4j包冲突导致PSML页面文件数据丢失
使用JetSpeed2进行二次开发时突然出现在保存Portlet配置信息时出现PSML页面文件数据丢失的情况,几经测试,最终发现是因为Portlet中的dom4j.jar与jetspeed应用中的do ...
- tomcat在idea中启动乱码
server,localhost log,catalina log分别乱码 打开tomcat/conf/目录下修改logging.properties 找到"utf-8"行更改为 ...
- TCP简单程序
服务器段: package com.dcz.socket; import java.io.IOException; import java.io.OutputStream; import java.n ...
- C#实现MD5WITHRSA签名
这是很久以前的写的一篇博客了,今天把他重新找出来整理一下发布到博客园 当时对接银联的时候搞了很久都没搞出来,后来一个偶然的机会发现类似的一个代码参考了一下终于弄好了 这段代码主要是实现了C#服务端对接 ...
- AndroidStudio第一次提交项目代码到git服务器/github
虽然使用AndroidStudio(以下简称as)开发并使用git管理代码已经有很长时间,但是第一次提交项目到git依然会很不顺利,网上的文章或许因为所使用版本比较老,并不一定完全凑效,因此写此笔记做 ...
- # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#
Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...
- Web开发者应掌握的12个Firebug技巧
来源: 廖煜嵘 相信很多从事Web开发工作的开发者都听说和使用过Firebug,但可能大部分人还不知道,其实它是一个在网页设计方面功能相当强大的编辑器,它 可以对HTML.DOM.CSS.HTTP和J ...
- JavaScript数据格式验证探讨
1.需求 修改某个文本框数据,要求对修改后的格式做验证(必须是数字). 注:实际需求比上述复杂,为了说明问题,这里特意简化了需求(如:对修改后数据依赖条件的判断,数据入库等). 2.关于NaN的探讨( ...