s3c24xx.c看i2c控制器驱动的编写

"./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随内核启动被注册, 所以控制器驱动在系统启动的时候就可以工作了

1275 static struct platform_driver s3c24xx_i2c_driver = { 1276 .probe = s3c24xx_i2c_probe, 1277 .remove = s3c24xx_i2c_remove, 1278 .id_table = s3c24xx_driver_ids, 1279 .driver = { 1280 .owner = THIS_MODULE, 1281 .name = "s3c-i2c", 1282 .pm = S3C24XX_DEV_PM_OPS, 1283 .of_match_table = of_match_ptr(s3c24xx_i2c_match), 1284 }, 1285 };

既然是遵循的platform编写, 那么所有的信息都要在一个platform_driver中描述, 分析也是围绕这个对象展开

--1276-->probe函数, 最重要的函数
--1278-->用于匹配的id表, 由于是平台文件编写的设备信息, 所以会使用这个域作为匹配的依据, 如下

132 static struct platform_device_id s3c24xx_driver_ids[] = { 133 { 134 .name = "s3c2410-i2c", 135 .driver_data = 0, 136 }, { 137 .name = "s3c2440-i2c", 138 .driver_data = QUIRK_S3C2440, 139 }, { 140 .name = "s3c2440-hdmiphy-i2c", 141 .driver_data = QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO, 142 }, { }, 143 };

我们可以在"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-->封装的平台信息, 是一个数组首地址, 每一个元素包括从机地址, 标志位, 总线编号等

probe

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/825e664c37210e780ae4cfe945a1ed77.html