在完成platform_device的添加之后,i2c子系统将进行platform_driver的注册过程。

platform_driver的注册通过调用初始化函数i2c_adapter_s3c_init函

数来完成。

i2c_adap_s3c_init()函数体如下:

static int __init i2c_adap_s3c_init(void)
{return platform_driver_register(&s3c24xx_i2c_driver);
}

platform_driver_register(&s3c24xx_i2c_driver),将完成向platform_bus总线注册platform_driver类型驱动

s3c24xx_i2c_driver的工作。s3c24xx_i2c_driver如下:

static struct platform_driver s3c24xx_i2c_driver = {.probe      = s3c24xx_i2c_probe,.remove        = s3c24xx_i2c_remove,.id_table = s3c24xx_driver_ids,.driver       = {.owner  = THIS_MODULE,.name    = "s3c-i2c",.pm  = S3C24XX_DEV_PM_OPS,},
};

id_table被初始化为s3c24xx_driver_ids:

static struct platform_device_id s3c24xx_driver_ids[] = {{.name     = "s3c2410-i2c",.driver_data = TYPE_S3C2410,}, {.name       = "s3c2440-i2c",.driver_data = TYPE_S3C2440,}, { },
};

platform_driver在注册到platform_bus总线的过程中会尝试将已注册的platform_driver

与已注册到platform_bus上的所有platform_device进行配对。

platform_bus总线的相关操作如下:

struct bus_type platform_bus_type = {.name      = "platform",.dev_attrs  = platform_dev_attrs,.match        = platform_match,.uevent       = platform_uevent,.pm      = &platform_dev_pm_ops,
};

配对过程通过调用总线的match方法实现,即platform_match函数。如下:

static int platform_match(struct device *dev, struct device_driver *drv)
{struct platform_device *pdev = to_platform_device(dev);struct platform_driver *pdrv = to_platform_driver(drv);/* Attempt an OF style match first */if (of_driver_match_device(dev, drv))return 1;/* Then try to match against the id table */if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;/* fall-back to driver name match */return (strcmp(pdev->name, drv->name) == 0);
}

可以看到函数中有

if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;

相关语句。

此处就是根据platfor_device和platform_driver的名字来实现配对。但是platform_driver有好几个名字

可以选择,通过id_table来实现配对。执行到此处,之前已注册到platform_bus的platform_device

型设备s3c_devicei2c0和现在刚注册到platform_bus总线的platfor_drver型驱动s3c24xx_i2c_drive将

实现配对成功。

成功配对之后将尝试进行probe

static int really_probe(struct device *dev, struct device_driver *drv)
{     。。。 。。。if (dev->bus->probe) {ret = dev->bus->probe(dev);if (ret)goto probe_failed;} else if (drv->probe) {ret = drv->probe(dev);if (ret)goto probe_failed;}。。。 。。。
}

有上述代码可知,成功配对后首先调用的是总线的probe,假如总线未初始化probe方法才会去

调用驱动中的probe,即platform_driver.drv->probe,而platform_bus本身未初始化probe方法,

所以此处调用驱动的probe方法,驱动的probe在注册过程中已被初始化

int platform_driver_register(struct platform_driver *drv)
{drv->driver.bus = &platform_bus_type;if (drv->probe)drv->driver.probe = platform_drv_probe;if (drv->remove)drv->driver.remove = platform_drv_remove;if (drv->shutdown)drv->driver.shutdown = platform_drv_shutdown;return driver_register(&drv->driver);
}

即直接调用函数platform_drv_probe,函数如下:

static int platform_drv_probe(struct device *_dev)
{struct platform_driver *drv = to_platform_driver(_dev->driver);struct platform_device *dev = to_platform_device(_dev);return drv->probe(dev);
}

函数的工作很简单,即通过_dev->driver找到包含它的platform_driver型驱动,然后再

调用此驱动的probe方法,即s3c24xx_i2c_probe函数。

probe函数的功能如下:

1.首先创建struct s3c24xx_i2c  *i2c。

i2c相关数据的初始化来源于s3c2_device_i2c0.dev.platdata。

2.通过i2c->adap.algo    = &s3c24xx_i2c_algorithm;初始化algo方法。

在write系统调用的时候会调用到s3c24xx_i2c_algorithm函数。

3.init_waitqueue_head(&i2c->wait); 初始化一个等待队列

4.s3c24xx_i2c_init (i2c);初始化i2c控制器,主要是对s3c24xx的i2c控制

寄存器进行一些操作,比如配置s3c2440i/o功能,设置从机地址,以及

设置i2c时钟频率等相关操作。时钟频率的设置参见博文。

5.request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
              dev_name(&pdev->dev), i2c);
申请中断,内核中的i2c读写是通过中断来实现的,具体稍后分析

6.i2c_add_numbered_adapter(&i2c->adap);最后向系统注册一个i2c adapter

这里需要着重注意第2、5、6点。

下面先分析第6点。第2、5点待到后面读写at24c02的时候再分析。

i2c子系统之platform_driver初始化——i2c_adap_s3c_init()相关推荐

  1. 协议[I2C]_I2C子系统之platform_driver初始化——I2C_adap_s3c_init()

    在完成platform_device的添加之后,i2c子系统将进行platform_driver的注册过程. platform_driver的注册通过调用初始化函数i2c_adapter_s3c_in ...

  2. linux驱动之I2C子系统

    目录 一.I2C基本原理 二.linux内核的I2C子系统详解 1.linux内核的I2C驱动框架总览 2.I2C子系统的4个关键结构体(kernel/include/linux/i2c.h) 3.关 ...

  3. Linux I2C子系统分析之(一) ----- 用GPIO模拟I2C总线

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

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

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

  5. 第九讲 Linux I2C子系统及mma8653重力传感器驱动编写

    2.I2C子系统 设备.总线.驱动模型: subsystem bus dev drv platform bus_type platform_device platform_driver I2C bus ...

  6. 【Linux驱动】I2C子系统与触摸屏驱动

    由于学习触摸屏驱动涉及到中断以及I2C相关的知识,因此先介绍一下I2C的驱动框架. 触摸屏与I2C总线的关系 关于I2C的基础概念和原理参考我的这篇博客:[裸机]嵌入式相关问题汇总(二.I2C通信概念 ...

  7. Linux i2c子系统

    一.前言 因为自己在研发过程中经常要涉及到tp驱动程序,而tp驱动就涉及到i2c驱动.经常可以看到在驱动程序中会定义一个struct i2c_driver的数据结构,并实现里面的某些成员,比如prob ...

  8. Linux驱动分析——I2C子系统

    stm32mp157  盘古开发板  Linux内核版本4.19 目录 1.朱有鹏老师视频笔记 2.I2C子系统的4个关键结构体 3.关键文件 4.i2c-core.c初步分析 ​4.1.smbus代 ...

  9. linux i2c子系统看不懂啊,Linux 下的I2C子系统

    Linux 下的I2C子系统 2013.7.16 本文分为两部分,一.设备模型 二.平台相关 . ================================================ 第一 ...

最新文章

  1. 通过flume-ng收集日志
  2. linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
  3. 开源后5个月,Google的深度学习都有哪些改变?
  4. 【机器学习课程笔记(吴恩达)】1.3 监督学习
  5. 两段关于统计日期的sql语句
  6. 蓝桥杯 ALGO-91 算法训练 Anagrams问题
  7. Java事务之八——分布式事务(Spring+JTA+Atomikos+Hibernate+JMS)
  8. 人们为何喜欢在社交网络发布个人状态?
  9. 【C语言视频教程完整版】从入门到进阶,适合C语言初学者计算机考研党考计算机二级大一大二学生学习观看~~~
  10. openvino系列 16. OpenVINO 手写字体识别 OCR
  11. 深度访谈: 怎样玩转天猫?看这九本书就够了
  12. 未来世界的幸存者 -- 阮一峰
  13. Angular Router的组件路由介绍
  14. C语言基础---3.格式化输出总结---%d ,%s,%f %.3f,%m.ns 以及sprintf函数
  15. 如果不想当程序员,学编程有什么用?答案显而易见!
  16. 学习笔记2-了解unik的设计
  17. FPGA中高时钟频率计数器设计
  18. 习题 8-28 打结(Knots, ACM/ICPC ACM/ICPC Jakarta 2012, UVa1624)
  19. 蓄电池与超级电容混合储能并网matlab simulink仿真模型
  20. linux文件赋予用户权限,Linux 给用户赋予操作权限

热门文章

  1. 魔岩三杰94红堪演唱会
  2. 算法频繁调整,SEO你应该关注点击量,还是SEO排名?
  3. EllisysBluetoothAnalyzer 下载 最新版
  4. 武汉大学计算机学院 余老师,邹勤 - 教师简历 CV- 武汉大学计算机学院
  5. 测试爬虫 爬取百度贴吧 爬取百度搜图图片
  6. Linux常用查看文件内容命令
  7. 收割90后,这些小程序玩出新高度
  8. 逆袭Futter? Facebook 发布全新跨平台引擎 Hermes!
  9. C语言输入输出各种格式 %+格式符(d o x u e f)
  10. IDEA项目覆盖黄色