“./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就执行