参考: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驱动框架(二)的更多相关文章

  1. I2C驱动框架(四)

    参考:I2C子系统之platform_driver初始化——I2C_adap_s3c_init() 在完成platform_device的添加之后,i2c子系统将进行platform_driver的注 ...

  2. I2C驱动框架 (kernel-3.4.2)

    先用韦老师的图: 注:  新版本内核的i2c驱动框架采用了    i2c_client -------> i2c_bus_type  <-------- i2c_driver   框架 如 ...

  3. I2C驱动框架(三)

    参考:I2C子系统之platform_device初始化——smdk2440_machine_init() I2C驱动框架还应用了另一种总线-设备-驱动模型,平台设备总线platform_bus_ty ...

  4. I2C驱动框架(kernel-2.6.22.6)

    以用i2c通信的实时时钟为例 框架入口源文件:i2c_m41t11.c (可根据入口源文件,再按着框架到内核走一遍) 内核版本:linux_2.6.22.6   硬件平台:JZ2440 以下是驱动框架 ...

  5. Linux 驱动框架---i2c驱动框架

    i2c驱动在Linux通过一个周的学习后发现i2c总线的驱动框架还是和Linux整体的驱动框架是相同的,思想并不特殊比较复杂的内容如i2c核心的内容都是内核驱动框架实现完成的,今天我们暂时只分析驱动开 ...

  6. 【Linux高级驱动】I2C驱动框架分析

    1.i2c-dev.c(i2c设备驱动组件层) 功能:1)给用户提供接口 i2c_dev_init  //入口函数 /*申请主设备号*/ register_chrdev(I2C_MAJOR(), &q ...

  7. Linux I2C驱动框架

    Linux的I2C体系结构分为3个组成部分: I2C核心(  i2c-core.c ): I2C核心提供了I2C总线驱动和设备驱动的注册.注销方法.I2C通信方法("algorithm&qu ...

  8. I2C驱动框架(五)

    参考:I2C子系统之 adapter driver注册——I2C_dev_init() i2c的操作在内核中是当做字符设备来操作的,相关初始化在由i2c_dev_init函数来初始化. static ...

  9. I2C驱动框架(一)

    参考:I2C子系统之内核中I2C子系统的结构 结合vmlinux.lds和Makefile可确定i2c初始化函数的执行顺序如下: 1./dricer/i2c/i2c-core.c中的函数:i2c_in ...

随机推荐

  1. 根据select中选定option触发不同事件

    做公司项目,要实现一个小需求,根据下拉框选定的数据,绑定不同的事件.我的思路是获取select下面的option值,然后给它们定义不同的点击事件,但是在使用中option不能添加类,同时没有click ...

  2. Sawgger框架

    简介详情:https://blog.csdn.net/sanyaoxu_2/article/details/80555328

  3. 089 Gray Code 格雷编码

    格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异.给定一个代表编码总位数的非负整数 n,打印格雷码序列.格雷码序列必须以0开头.例如, 给定 n = 2, 返回 [0,1,3 ...

  4. python对文件的压缩解压

    python自带的zipfile的模块支持对文件的压缩和解压操作 zipfilp.ZipFile 表示创建一个zip对象 zipfile.ZipFile(file[, mode[, compressi ...

  5. 接口文档管理工具rap

    git地址:  https://github.com/thx/RAP wiki : https://github.com/thx/RAP/wiki/home_cn 视频教程: http://thx.g ...

  6. 剑指tomcat之多项目部署问题

    部署项目时遇到的问题,tomcat的webapps文件夹中有两个war包,但每次启动Tomcat服务时,只会默认启动一个war包. 解决方案一:在Tomcat主页中进入应用管理页面,手动开启项目.(进 ...

  7. Eclipse集成Maven环境(出现jar的解析或者缺失问题)(或者出现Invalid classpath publish/export dependency /common. Project entries not supported)的统一整理

    在正确配置完Maven,和Maven IntegrationFor Eclipse之后,新建了一个Maven Project 和一个Maven Module,发现新建的Module项目下的pom.xm ...

  8. 内存泄露,C++

    内存泄露,C++通常是指new出来的内存没有delete掉.在你的代码里边,new了一块内存,然后马上就delete,自然就没有内存泄露了(呃……其实我也不确定啦,因为你用的是delete,而不是de ...

  9. Android 6.0 运行时权限处理完全解析 (摘抄)

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/50709663: 本文出自:[张鸿洋的博客] 一.概述 随着Android 6. ...

  10. IOS之网络状态设和NSUserDefaults的synchronize

    #pragma mark - check net status int apiCheckNetStatus() { Reachability *reachNet = [Reachability rea ...