我们首先从/drivers/i2c/chips/eeprom.c来分析,这是驱动那一块的:
static struct i2c_driver eeprom_driver = {
.driver = {
.name = "eeprom",
},
.id = I2C_DRIVERID_EEPROM,
.attach_adapter = eeprom_attach_adapter,
.detach_client = eeprom_detach_client,
};
i2c_add_driver(&eeprom_driver);
i2c_register_driver(THIS_MODULE, driver);
driver->driver.bus = &i2c_bus_type;
/* 把驱动加入iic总线驱动列表 */
list_add_tail(&driver->list,&drivers);
/* 遍历适配器链表,对每一个适配器调用driver->attach_adapter函数 */
list_for_each_entry(adapter, &adapters, list) {
driver->attach_adapter(adapter);}
eeprom_attach_adapter(struct i2c_adapter *adapter)
i2c_probe(adapter, &addr_data, eeprom_detect);
i2c_probe_address(adapter, address_data->normal_i2c[i], -1, found_proc);//见注释1
i2c_smbus_xfer(adapter, addr, 0, 0, 0,I2C_SMBUS_QUICK, NULL);
i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data);
i2c_transfer(adapter, msg, num)
adap->algo->master_xfer
/* 这个函数在适配器里面有定义 */
s3c24xx_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msgs, int num)
/* S信号和设备地址最终通过适配器里面的这个函数来发送 */
s3c24xx_i2c_doxfer(i2c, msgs, num);
我们再来另外一个框架,/drivers/i2c/busses/i2c-s3c2410.c,这是适配器那一块的:
platform_driver_register(&s3c2410_i2c_driver);
s3c24xx_i2c_probe(struct platform_device *pdev)
s3c24xx_i2c_init(i2c);
request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,pdev->name, i2c);
i2c_add_adapter(&i2c->adap);
i2c_add_adapter(&i2c->adap);
i2c_register_adapter(adapter);
list_add_tail(&adap->list, &adapters);
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
if (driver->attach_adapter)
driver->attach_adapter(adap);}
注释1:
i2c_probe_address(adapter, address_data->normal_i2c[i], -1, found_proc);这个函数会将address_data里面定义的设备地址通过适配器里面的发送函数发送给设备,如果存在相应的设备的话就会调用found_proc函数,在这个函数里面做了如下事情:
i2c_probe_address(adapter, address_data->normal_i2c[i], -1, found_proc);这个函数会将address_data里面定义的设备地址通过适配器里面的发送函数发送给设备,如果存在相应的设备的话就会调用found_proc函数,在这个函数里面做了如下事情:
struct i2c_client *new_client;//定义一个i2c_client结构体,下面需要设置
new_client->addr = address;//这个是设备地址
new_client->adapter = adapter;//这时找到的适配器
new_client->driver = &eeprom_driver;//这是驱动
i2c_attach_client(new_client);//添加客户
如此就把设备、驱动、适配器三者有机的联系起来了哦!
分析:
为了方便观察我们来做一个框图:
![IIC总线驱动程序框架分析 - 小白 - 小白的博客](http://img9.ph.126.net/5UIsnA66U4lnimn_JhajVA==/1100848633932939219.jpg)
在驱动这边:
(1)将定义的i2c_driver结构体加入总线的驱动链表
(2)遍历适配器,调用驱动里面的attach_adapter函数
(3)attach_adapter函数会调用i2c_probe()函数,它的第二个参数是设备地址,第三个参数是功能函数。它会调用适配器里面的master_xfer函数发送这个地址,来检测是否存在这样的设备,如果存在就会调用功能函数。
在适配器这边:
(1)定义适配器,并且加入总线适配器链表
(2)遍历每一个驱动,调用驱动的attach_adapter函数
(3)attach_adapter函数会调用i2c_probe()函数,它的第二个参数是设备地址,第三个参数是功能函数。它会调用适配器里面的master_xfer函数发送这个地址,来检测是否存在这样的设备,如果存在就会调用功能函数。
我们可以看出来不管是先加在驱动还是先加载适配器都是一样的哦!