i2c驱动分析
来源:互联网 发布:数据分析师有哪些证书 编辑:程序博客网 时间:2024/04/28 11:55
234 * struct i2c_board_info - template for device creation235 * @type: chip type, to initialize i2c_client.name236 * @flags: to initialize i2c_client.flags237 * @addr: stored in i2c_client.addr238 * @platform_data: stored in i2c_client.dev.platform_data239 * @archdata: copied into i2c_client.dev.archdata240 * @of_node: pointer to OpenFirmware device node241 * @irq: stored in i2c_client.irq242 *243 * I2C doesn't actually support hardware probing, although controllers and244 * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's245 * a device at a given address. Drivers commonly need more information than246 * that, such as chip type, configuration, associated IRQ, and so on.247 *248 * i2c_board_info is used to build tables of information listing I2C devices249 * that are present. This information is used to grow the driver model tree.250 * For mainboards this is done statically using i2c_register_board_info();251 * bus numbers identify adapters that aren't yet available. For add-on boards,252 * i2c_new_device() does this dynamically with the adapter already known.253 */254 struct i2c_board_info {255 char type[I2C_NAME_SIZE];256 unsigned short flags;257 unsigned short addr;258 void *platform_data;259 struct dev_archdata *archdata;260 struct device_node *of_node;261 int irq;262 };263 264 /**265 * I2C_BOARD_INFO - macro used to list an i2c device and its address266 * @dev_type: identifies the device type267 * @dev_addr: the device's address on the bus.268 *269 * This macro initializes essential fields of a struct i2c_board_info,270 * declaring what has been provided on a particular board. Optional271 * fields (such as associated irq, or device-specific platform_data)272 * are provided using conventional syntax.273 */274 #define I2C_BOARD_INFO(dev_type, dev_addr) \275 .type = dev_type, .addr = (dev_addr)
Probe方式(new style)
● 构建i2c_driver
和LEGACY方式一样,也需要构建i2c_driver,但是内容有所不同。
static struct i2c_driver pca953x_driver = {
.driver = {
.name= "pca953x",
},
.probe= pca953x_probe, //当有i2c_client和i2c_driver匹配时调用
.remove= pca953x_remove,//注销时调用
.id_table= pca953x_id,//匹配规则
};
● 注册i2c_driver
static int __init pca953x_init(void)
{
return i2c_add_driver(&pca953x_driver);
}
module_init(pca953x_init);
在注册i2c_driver的过程中,是将driver注册到了i2c_bus_type的总线上。此总线的匹配规则是:
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
可以看出是利用i2c_client的名称和id_table中的名称做匹配的。本驱动中的id_table为
static const struct i2c_device_id pca953x_id[] = {
{ "pca9534", 8, },
{ "pca9535", 16, },
{ "pca9536", 4, },
{ "pca9537", 4, },
{ "pca9538", 8, },
{ "pca9539", 16, },
{ "pca9554", 8, },
{ "pca9555", 16, },
{ "pca9557", 8, },
{ "max7310", 8, },
{ }
};
看到现在我们应该会有这样的疑问,在Adapter模式中,i2c_client是我们自己构造出来的,而现在的i2c_client是从哪来的呢?看看下面的解释
● 注册i2c_board_info
对于Probe模式,通常在平台代码中要完成i2c_board_info的注册。方法如下:
static struct i2c_board_info__initdata test_i2c_devices[] = {
{
I2C_BOARD_INFO("pca9555", 0x27),//pca9555为芯片名称,0x27为芯片地址
.platform_data = &pca9555_data,
},
{
I2C_BOARD_INFO("mt9v022", 0x48),
.platform_data = &iclink[0], /* With extender */
},
{
I2C_BOARD_INFO("mt9m001", 0x5d),
.platform_data = &iclink[0], /* With extender */
},
};
i2c_register_board_info(0, test_i2c_devices,ARRAY_SIZE(test_i2c_devices)); //注册
上面申请这个数组表示i2c总线上面有这么些设备,包含驱动名称,从地址地址,中断号什么的,还有私有数据结构
i2c_client就是在注册过程中构建的。但有一点需要注意的是i2c_register_board_info并没有EXPORT_SYMBOL给模块使用。
● 字符驱动注册
在Probe方式下,添加字符驱动的位置在pca953x_probe中。
static int __devinit pca953x_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
……
/****字符设备驱动注册位置****/
……
return 0;
}
● 注销i2c_driver
static void __exit pca953x_exit(void)
{
i2c_del_driver(&pca953x_driver);
}
module_exit(pca953x_exit);
● 注销字符设备驱动
在Probe方式下,注销字符驱动的位置在pca953x_remove中。
static int __devinit pca953x_remove (struct i2c_client *client)
{
……
/****字符设备驱动注销的位置****/
……
return 0;
}
● I2C设备的数据交互方法(即:调用适配器操作设备的方法)和Adapter方式下相同。
函数初始化函数i2c_register_board_info(0, msm_i2c_board_info,ARRAY_SIZE(msm_i2c_board_info));这个函数相当于就会去注册i2c设备信息实现如下int __initi2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len){ int status; mutex_lock(&__i2c_board_lock); /* dynamic bus numbers will be assigned after the last static one */ if (busnum >= __i2c_first_dynamic_bus_num) __i2c_first_dynamic_bus_num = busnum + 1; for (status = 0; len; len--, info++) { struct i2c_devinfo *devinfo; devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); if (!devinfo) { pr_debug("i2c-core: can't register boardinfo!\n"); status = -ENOMEM; break; } devinfo->busnum = busnum; devinfo->board_info = *info; list_add_tail(&devinfo->list, &__i2c_board_list); } mutex_unlock(&__i2c_board_lock); return status;}
现在回到函数i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)中
list_add_tail(&devinfo->list, &__i2c_board_list);
这句话会将i2c设备添加到全局链表__i2c_board_list上面去
实际上到这里如果我们在arch这边的board——info里面定义了设备的话,那么这是i2c设别在这条链表上面了,
static void i2c_scan_static_board_info(struct i2c_adapter *adapter){ struct i2c_devinfo *devinfo; mutex_lock(&__i2c_board_lock); list_for_each_entry(devinfo, &__i2c_board_list, list) { if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter, &devinfo->board_info)) printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n", i2c_adapter_id(adapter), devinfo->board_info.addr); } mutex_unlock(&__i2c_board_lock);}
- linux I2C驱动分析
- linux I2C驱动分析
- Linux I2C 驱动分析
- I2C驱动分析
- Linux驱动I2C分析
- linux i2c 驱动分析
- I2C驱动分析
- I2C驱动分析
- Linux--I2C驱动分析
- linux i2c驱动分析
- i2c驱动分析
- linux i2c驱动分析
- i2c驱动分析
- Linux I2C 驱动分析
- i2c内核驱动分析
- Linux I2C驱动分析
- Linux I2C子系统分析-I2C总线驱动
- Linux I2C子系统分析-I2C设备驱动
- 对于飞凌公司的ok6410开发板linux2.6.36内核编译方法
- extern与static
- java中io流下载文件实例
- 多个字段的in 和 not in 及其替代写法(exists,not exists)
- 经典软件设计模型 - 插件模型
- i2c驱动分析
- 自定义ListView中的分割线
- Java多线程的volatile关键字
- dxsudio三维交互初见
- Spring容器对象(BeanFactory)
- HTTP协议详解
- TCP报文中的SYN,FIN,ACK,PSH,RST,URG
- sicily 1027
- 安装. Net 3.5