"./drivers/i2c/busses/i2c-s3c2410.c"是3.14.0内核中三星SoC的i2c控制器驱动程序, 本文试图通过对这个程序的分析, 剥离繁复的细节, 总结一套编写i2c主机控制器驱动的框架以及一个分析内核驱动的流程.
匹配之前 1287 static int __init i2c_adap_s3c_init(void) 1288 { 1289 return platform_driver_register(&s3c24xx_i2c_driver); 1290 } 1291 subsys_initcall(i2c_adap_s3c_init);--1291-->将主机控制器驱动在系统启动的时候就注册好
--1289-->这个驱动是基于platform总线的, 设备信息的部分在板级文件i2c_board_info中描述并作为platform_device随内核启动被注册, 所以控制器驱动在系统启动的时候就可以工作了
既然是遵循的platform编写, 那么所有的信息都要在一个platform_driver中描述, 分析也是围绕这个对象展开
--1276-->probe函数, 最重要的函数
--1278-->用于匹配的id表, 由于是平台文件编写的设备信息, 所以会使用这个域作为匹配的依据, 如下
我们可以在"arch/arm/plat-samsung"中找到相应的设备信息
485 struct platform_device s3c_device_i2c0 = { 486 .name = "s3c2410-i2c", 487 .id = 0, 488 .num_resources = ARRAY_SIZE(s3c_i2c0_resource), 489 .resource = s3c_i2c0_resource, 490 };二者一匹配, probe就执行!
匹配之后一旦匹配上, 分析流程就会有点变化, 驱动开发都是基于面向对象的思想的, 内核虽然给我们封装了很多"类", 但当我们开发一个具体的驱动的时候, 还是要对其进行"继承", 进而创建针对具体设备的资源对象, 资源对象管理着驱动中诸多函数的共用资源, 是整个驱动运行过程中资源管理者与桥梁, 主要包括:内核类+资源(io, irq,时钟, 寄存器)+状态表示+其他,所以, 设计驱动的工作中很重要的一个工作就是"设计资源类". 下面就是三星设计的类, 我把次要的部分剔除了
资源类资源对象是整个驱动运作的核心, 所有的方法需要的资源都是对这个对象的操作, 它的设计是迭代的过程, 但当整个框架搭起来之后, 不应该有大的变化
103 struct s3c24xx_i2c { 104 wait_queue_head_t wait; 108 struct i2c_msg *msg; 109 unsigned int msg_num; 110 unsigned int msg_idx; 111 unsigned int msg_ptr; 113 unsigned int tx_setup; 114 unsigned int irq; 116 enum s3c24xx_i2c_state state; 117 unsigned long clkrate; 119 void __iomem *regs; 120 struct clk *clk; 121 struct device *dev; 122 struct i2c_adapter adap; 124 struct s3c2410_platform_i2c *pdata; 125 int gpios[2]; 130 };struct s3c24xx_i2c
--108-->收到的i2c-core.c发送过来的i2c_msg对象数组首地址
--109-->i2c_msg数组的元素个数
--110-->i2c_msg数组元素的索引
--114-->使用的中断号
--116-->当前控制器的状态, 用枚举量表示STATE_IDLE, STATE_START,STATE_READ,STATE_WRITE,STATE_STOP
--117-->时钟频率
--120-->时钟
--121-->属于device, 按照device来管理
--122-->构造并使用的i2c_adapter对象, 和上一篇的框架图对应
--124-->封装的平台信息, 是一个数组首地址, 每一个元素包括从机地址, 标志位, 总线编号等