平台:RK3399

使用设备树描述板级资源;

框架:

linux i2c框架同样采用分层、分离的模式设计;从上到下分为  app调用层、i2c core层、驱动层;驱动层又分为 cpu平台 i2c控制器相关的驱动层以及 i2c总线上挂接的设备驱动程序;而分离的思想则体现在板级相关的信息放在设备树上实现,而通用的读写、初始化流程、操作流程等则放到驱动里面实现(类似platform总线驱动);

具体分析:

1. cpu i2c控制器驱动(adpter)

static struct platform_driver rk3x_i2c_driver ={

.probe=rk3x_i2c_probe,

.remove=rk3x_i2c_remove,

.driver={

.name= "rk3x-i2c",

.of_match_table=rk3x_i2c_match,

.pm= &rk3x_i2c_pm_ops,

},

};

module_platform_driver(rk3x_i2c_driver)

RK3399采用以上方法向内核定义了一个platform driver,内核启动的时候,会再设备树里面I2C节点找到对应的设备节点定义compatible = "rockchip,rk3399-i2c"; ,由于 of_match_table 里面可以找到rockchip,rk3399-i2c,所以紧接着会调用 rk3x_i2c_probe 函数;rk3x_i2c_probe 函数主要是向内核注册了cpu i2c控制器驱动,并且扫描设备树里面i2c所有节点的设备信息(包括I2C根节点的信息),然后将添加扫描到的i2c设备信息加入i2c bus总线维护的链表里面 (bus->p->klist_devices),然后再用设备的名称和 i2c设备驱动里面的设备名称匹配,如果匹配成功,则调用i2c设备的probe函数:

具体分析如下:

ret = i2c_add_adapter(&i2c->adap);

adpter注册及device注册调用流程如下:

ret = i2c_add_adapter(&i2c->adap);

i2c_register_adapter(adapter);

of_i2c_register_devices(adap);//扫描设备树I2C总线子节点信息;包括挂接的设备名称及地址!

for_each_available_child_of_node(adap->dev.of_node, node) {if(of_node_test_and_set_flag(node, OF_POPULATED))continue;

of_i2c_register_device(adap, node);

}

再深入 of_i2c_register_device(adap, node) 函数调用分析:

of_i2c_register_device(adap, node)

i2c_new_device(adap,&info); //info里面便包含了i2c总线挂接设备的名称及地址

status = device_register(&client->dev); //完成 client 设备的创建

returndevice_add(dev);

error= bus_add_device(dev); //将设备加入bus总线

bus_probe_device(dev); //开始设备的匹配

再深入看下 bus_probe_device(dev); // 开始设备的匹配

void bus_probe_device(struct device *dev)

{struct bus_type *bus = dev->bus;struct subsys_interface *sif;if (!bus)return;if (bus->p->drivers_autoprobe) //在i2c_core初始化的时候已经置一

device_initial_probe(dev);

mutex_lock(&bus->p->mutex);

list_for_each_entry(sif,&bus->p->interfaces, node)if (sif->add_dev)

sif->add_dev(dev, sif);

mutex_unlock(&bus->p->mutex);

}

关注以上代码里面的  device_initial_probe(dev); 函数,其调用流程如下

device_initial_probe(dev);

__device_attach(dev,true);

ret= bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver);

if (!driver_match_device(drv, dev)) // 开始调用 i2c bus总线的match函数,匹配设备和设备驱动

return driver_probe_device(drv, dev); // 匹配成功,则调用设备驱动的probe函数

至此, adpter及设备端的注册匹配基本结束;

另外还有设备驱动部分,拿声卡 es8316来分析;

先分配一个 i2c driver结构体

static struct i2c_driver es8316_i2c_driver ={

.driver={

.name= "es8316",

.of_match_table=es8316_of_match,

},

.probe=es8316_i2c_probe,

.remove=es8316_i2c_remove,

.shutdown=es8316_i2c_shutdown,

.id_table=es8316_i2c_id,

};

module_i2c_driver(es8316_i2c_driver);

module_i2c_driver(es8316_i2c_driver)向内核注册i2c driver;主要完成了设备驱动的注册,及跟设备的匹配,如果匹配成功,则调用probe函数es8316_i2c_probe, 具体流程如下

i2c_register_driver

res= driver_register(&driver->driver);

ret=bus_add_driver(drv);

klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);

error= driver_attach(drv);

从上面流程可以看出,已经完成了把驱动放入 bus 总线维护的 drivers 链表  klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);

再具体深入下 driver_attach(drv);

driver_attach(drv);return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);if (!driver_match_device(drv, dev))

driver_probe_device(drv, dev);

至此,便完成了设备驱动与设备的匹配和设备驱动probe的调用

至此,i2c驱动基本完成,而其余跟设备相关操作,均可在probe函数里实现,比如声卡的初始化等;

基于linux4.4程序,linux驱动之i2c总线驱动调用分析【基于linux4.4】相关推荐

  1. Linux设备驱动篇——[I2C设备驱动-1]

    Linux 设备驱动篇之I2c设备驱动 fulinux 一.I2C驱动体系 虽然I2C硬件体系结构和协议都很容易理解,但是Linux I2C驱动体系结构却有相当的复杂度,它主要由3部分组成,即I2C设 ...

  2. linux 深入理解I2C内核驱动

    系列文章 I.MX6ULL 手册查找使用方法 实战点亮LED(寄存器版) I.MX6ULL 手册查找使用方法 实战点亮LED(固件库版本) linux 字符设备驱动实战 linux LED设备驱动文件 ...

  3. SylixOS iMX6平台I2C总线驱动

    原理概述 I2C总线驱动概述 I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和MasterXfer的实现函数.驱动程序包含初始化I2C总 ...

  4. arm linux i2c 总线驱动,ARM-Linux中I2C总线驱动开发

    摘  要: 针对I2C总线的特点,Linux内核中定义了I2C驱动体系结构.在分析Linux的I2C总线驱动体系结构基础上,介绍了在S3C2410中设计I2C总线驱动的方法. 关键词: ARM-Lin ...

  5. Linux设备驱动之——I2C总线

    2  I2C子系统 2.1 LinuxI2C子系统架构 在内核中已经提供I2C子系统,所以在做I2C驱动之前,就必须要熟悉该子系统. 2.2 三大组成部分 1.I2C核心(i2c-core) I2C核 ...

  6. Linux I2C子系统分析-I2C总线驱动

    在drivers/i2c/busses下包含各种I2C总线驱动,如S3C2440的I2C总线驱动i2c-s3c2410.c,使用GPIO模拟I2C总线的驱动i2c-gpio.c,这里只分析i2c-gp ...

  7. i.MX6ULL终结者Linux I2C驱动实验IMX6ULL的I2C总线驱动分析

    在上一节中我们了解了I2C框架分为I2C核心.I2C总线驱动和I2C设备驱动三部分.其中I2C总线驱动就是SOC的I2C控制器驱动,一般来说都是SOC厂家实现好的.而I2C设备驱动是用户根据自己不同的 ...

  8. Linux下的USB总线驱动 mouse

    Linux下的USB总线驱动(03)--USB鼠标驱动 usbmouse.c USB鼠标驱动 usbmouse.c 原文链接:http://www.linuxidc.com/Linux/2012-12 ...

  9. *Linux下的USB总线驱动 u盘驱动分析*

    Linux下的USB总线驱动(三) u盘驱动分析 版权所有,转载请说明转自 http://my.csdn.net/weiqing1981127 https://www.xuebuyuan.com/13 ...

最新文章

  1. IT餐馆—第二回 私活
  2. python计算机基础_python计算机基础
  3. html5学习笔记(html5新标签aside)
  4. IC设计常见设计思想
  5. 【ArcGIS风暴】ArcGIS自动生成标识码(BSM)的两种方法案例教程
  6. 一条SQL语句的执行过程
  7. mysql php 乱码问题_解决php与mysql中文乱码问题
  8. anywhere执行时端口被占用Address already in use:8080解决方法
  9. android图片上加有汉字,Android 为图片添加文字水印
  10. Servlet and Tomcat
  11. Xcode Developer Tools
  12. Tarjan+topsort(DP)【P3387】 [模板]缩点
  13. 【java】使用Stanford CoreNLP处理英文(词性标注/词形还原/解析等)
  14. OA项目实战学习(3)——实现岗位管理增删改查
  15. Cesium火灾动画(模型动画,粒子特效)
  16. 【华为OD机试真题 python】补种未成活胡杨 【2022 Q4 | 100分】
  17. IDEA安装MAVEN
  18. 25268 Problem E 例题3-5 求一元二次方程的根
  19. 【MD5】校验下载文件完整性
  20. 喝一碗孟婆汤nbsp;走一遍奈何桥

热门文章

  1. 【diannaoxitong】简单几步可将phone照片流删除的干干净净?
  2. C4D制作一个物体变换成另一个物体动画
  3. 生肖 java_Java生肖查询
  4. Android实现生肖特征查询,intent实现下拉框文本传递
  5. 关闭CPU C State 解决卡屏死机问题
  6. 深度学习之生成式模型
  7. router.beforeEach方法用法
  8. CentOS7.5搭建ORACLE RAC+DG
  9. 最高的情商,就是满怀感恩去工作
  10. 解读Keras在ImageNet中的应用:详解5种主要的图像识别模型