IIC总线驱动程序框架分析

来源:互联网 发布:java 堆栈信息怎么看 编辑:程序博客网 时间:2024/05/29 09:15
我们首先从/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函数,在这个函数里面做了如下事情:
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总线驱动程序框架分析 - 小白 - 小白的博客

在驱动这边:
(1)将定义的i2c_driver结构体加入总线的驱动链表
(2)遍历适配器,调用驱动里面的attach_adapter函数
(3)attach_adapter函数会调用i2c_probe()函数,它的第二个参数是设备地址,第三个参数是功能函数。它会调用适配器里面的master_xfer函数发送这个地址,来检测是否存在这样的设备,如果存在就会调用功能函数。

在适配器这边:
(1)定义适配器,并且加入总线适配器链表
(2)遍历每一个驱动,调用驱动的attach_adapter函数
(3)attach_adapter函数会调用i2c_probe()函数,它的第二个参数是设备地址,第三个参数是功能函数。它会调用适配器里面的master_xfer函数发送这个地址,来检测是否存在这样的设备,如果存在就会调用功能函数。

我们可以看出来不管是先加在驱动还是先加载适配器都是一样的哦!
原创粉丝点击