总线设备驱动模型之i2c

版权声明:本文为博主原创文章,任何组织或者个人可以在任何媒介上发表或转载我的文章、图片等.且转载后必须注明出处和邮箱,博客地址(https://blog.csdn.net/u011011827),本人邮箱([email protected]) https://blog.csdn.net/u011011827/article/details/89424977

i2c 设备

  • 匹配
drivers/i2c/i2c-core.c
static int i2c_device_match(struct device *dev, struct device_driver *drv);

struct i2c_client   *client = i2c_verify_client(dev);
struct i2c_driver   *driver;
1. 前提
client 必须为非NULL
client->name为 设备节点中 compatible 属性的 第一个值 compatible = "xxx", "yyy"; 中的 "xxx"
2 共支持3种匹配方式
2.1 OF
of_driver_match_device(dev, drv) // 设备树中的 compatible 和 i2c_device_driver.driver.of_match_table[0].compatible 匹配
2.2 ACPI
acpi_driver_match_device(dev, drv) // 忽略,不考虑
2.3 id table
driver->id_table // i2c_device_driver.id_table	和 client->name 匹配
	i2c_match_id(driver->id_table, client)

2.1 举例
//设备树
node-i2c@40{
	compatible = "xxx","yyy";
}
//驱动
static const struct of_device_id ids[] = {                                       
    { .compatible = "xxx"},                               
    {  },                                                                        
};                                                                               
                                                                                   
static const struct i2c_device_id i2c_ids[] = {                                               { },                                                                          
};                                                                               
                                                                                   
static struct i2c_driver i2c_device_driver = {                                   
    .driver = {                                                                  
        .name   = "something_SUIBIAN_BUT_MUST_HAVE",                    
        .owner  = THIS_MODULE,                                                   
        .of_match_table = ids,
    },                                                                              
    .probe      = i2c_device_probe,                                                 
    .remove     = i2c_device_remove,                                                
    .id_table   = i2c_ids, //不可以为null ,若为null ,__driver_attach->driver_probe_device->really_probe->i2c_device_probe 会检测 driver->id_table 是不是为空,若为空,不调用 probe // 对应 linux_4.0/drivers/i2c/i2c-core.c 中的 644 645 行
  }; 

2.3 举例
//设备树
node-i2c@40{
	compatible = "xxx","yyy"; // 匹配关键
}
//驱动                                                                       
static const struct i2c_device_id i2c_ids[] = {    
    { .name = "xxx", }, // 匹配关键
    { },                                                                          
};                                                                               
                                                                                   
static struct i2c_driver i2c_device_driver = {                                   
    .driver = {                                                                  
        .name   = "something_SUIBIAN_BUT_MUST_HAVE",                    
        .owner  = THIS_MODULE,                                                   
    },                                                                              
    .probe      = i2c_device_probe,                                                 
    .remove     = i2c_device_remove,                                                
    .id_table   = i2c_ids, //不可以为null ,若为null ,__driver_attach->driver_probe_device->really_probe->i2c_device_probe 会检测 driver->id_table 是不是为空,若为空,不调用 probe // 对应 linux_4.0/drivers/i2c/i2c-core.c 中的 644 645 行
}; 
  • 匹配成功之后
匹配成功之后,也不一定回最终执行 probe 函数
匹配成功之后,还要检查 driver->id_table 是否为空, 注意 driver->id_table 不能为空
  • sys 目录
/sys/bus/i2c/devices/i2c-1 // i2c 控制器
/sys/bus/i2c/drivers/something_SUIBIAN_BUT_MUST_HAVE // i2c 驱动
sysfs_create_group 在 /sys/bus/i2c/devices/i2c-1 连接目录的 1-0040 下面
  • device sys
wit@vexpress:/sys/devices/platform/smb/smb:motherboard/smb:motherboard:iofpga@7,00000000/10002000.i2c/i2c-1/1-0040 # ls -l -R
.:
total 0
lrwxrwxrwx    1 0        0                0 Apr 20 14:04 driver -> ../../../../../../../../bus/i2c/drivers/something_SUIBIAN_BUT_MUST_HAVE // 这个文件夹名就是 driver.name
-r--r--r--    1 0        0             4096 Apr 20 14:04 modalias
-r--r--r--    1 0        0             4096 Apr 20 14:04 name // 设备节点中 compatible中的第一个值
-rw-r--r--    1 0        0             4096 Apr 20 14:04 node_one 
-r--r--r--    1 0        0             4096 Apr 20 14:04 node_two
drwxr-xr-x    2 0        0                0 Apr 20 14:04 power
lrwxrwxrwx    1 0        0                0 Apr 20 14:04 subsystem -> ../../../../../../../../bus/i2c
-rw-r--r--    1 0        0             4096 Apr 20 14:04 uevent

./power:
total 0
-rw-r--r--    1 0        0             4096 Apr 20 14:05 autosuspend_delay_ms
-rw-r--r--    1 0        0             4096 Apr 20 14:05 control
-r--r--r--    1 0        0             4096 Apr 20 14:05 runtime_active_time
-r--r--r--    1 0        0             4096 Apr 20 14:05 runtime_status
-r--r--r--    1 0        0             4096 Apr 20 14:05 runtime_suspended_time
  • driver sys
wit@vexpress:/sys/bus/i2c/drivers/something_SUIBIAN_BUT_MUST_HAVE # ls -l 
total 0
lrwxrwxrwx    1 0        0                0 Apr 20 14:08 1-0040 -> ../../../../devices/platform/smb/smb:motherboard/smb:motherboard:iofpga@7,00000000/10002000.i2c/i2c-1/1-0040
--w-------    1 0        0             4096 Apr 20 14:08 bind
--w-------    1 0        0             4096 Apr 20 14:08 uevent
--w-------    1 0        0             4096 Apr 20 14:08 unbind
  • probe 参数
static int i2c_device_probe (struct i2c_client *client, const struct i2c_device_id *id);
id->name:chip-name-i2c // 如果不是 id table 匹配的话,id 为NULL.
id->driver_data:0  // 如果不是 id table 匹配的话,id 为NULL.
    
client->flags:0
client->addr:64
client->name:chip-name-i2c
client->irq:40
  • 相互获取
static int i2c_device_probe (struct i2c_client *client, const struct i2c_device_id *id);
client 到其他
获取 dev :client->dev
获取 设备树节点 :client->dev.of_node
获取驱动 :client->dev->driver

dev 到其他
struct i2c_client *client = to_i2c_client(dev);

  • i2c 中私有数据的存放
client 这一层
	bu21013_data->client = client;
	i2c_set_clientdata(client, bu21013_data);
	
	struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
	struct i2c_client * client = bu21013_data->client;
device 这一层
	dev->driver_data = bu21013_data;
	
	struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
	dev_get_platdata

猜你喜欢

转载自blog.csdn.net/u011011827/article/details/89424977