当前位置:文档之家› Linux I2C(一)之常用的几种实例化(i2c_client )

Linux I2C(一)之常用的几种实例化(i2c_client )


* struct i2c_board_info - template for device creation * @type: chip type, to initialize i2c_ * @flags: to initialize i2c_client.flags * @addr: stored in i2c_client.addr * @platform_data: stored in i2c_client.dev.platform_data * @archdata: copied into i2c_client.dev.archdata * @of_node: pointer to OpenFirmware device node * @acpi_node: ACPI device node * @irq: stored in i2c_client.irq * * I2C doesn't actually support hardware probing, although controllers and * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's * a device at a given address. Drivers commonly need more information than * that, such as chip type, configuration, associated IRQ, and so on. * * i2c_board_info is used to build tables of information listing I2C devices * that are present. This information is used to grow the driver model tree. * For mainboards this is done statically using i2c_register_board_info(); * bus numbers identify adapters that aren't yet available. For add-on boards, * i2c_new_device() does this dynamically with the adapter already known. */ struct i2c_board_info { char type[I2C_NAME_SIZE]; unsigned short flags; unsigned short addr; void *platform_data; struct dev_archdata *archdata; struct device_node *of_node; struct acpi_dev_node acpi_node; int irq; }; i2c_register_board_info: /** * i2c_register_board_info - statically declare I2C devices * @busnum: identifies the bus to which these devices belong * @info: vector of i2c device descriptors * @len: how many descriptors in the vector; may be zero to reserve * the specified bus number. * * Systems using the Linux I2C driver stack can declare tables of board info * while they initialize. This should be done in board-specific init code * near arch_initcall() time, or equivalent, before any I2C adapter driver is * registered. For example, mainboard init code could define several devices,
方一:
使用 arch/arm/mach-s3c24xx/mach-mini2440.c 举例: static struct i2c_board_info mini2440_i2c_devs[] __initdata = { { /* 遇到与”24c08 一样的名称”的驱动就会与之绑定, 0x50 是 I2C 设备的地址 */ I2C_BOARD_INFO("24c08", 0x50), .platform_data = &at24c08, }, }; /* 这里的 0 代表:i2c-0 总线 */ i2c_register_board_info(0, mini2440_i2c_devs, ARRAY_SIZE(mini2440_i2c_devs)); 到这里我们可以说就完成了第一种方式的实例化。 使用 i2c_register_board_info 去实例化必须知道我们使用的 I2C 设备是挂载到哪个总线 上,并知道设备的地址。 在 Linux 启 动 的 时 候 会 将 信 息 进 行 收 集 , i2c 适 配 器 会 扫 描 已 经 静 态 注 册 的 i2c_board_info,通过调用 i2c_register_board_info 函数将包含所有 I2C 设备的 i2c_board_info 信息的 i2c_devinfo 变量加入到__i2c_board_list 链表中,并调用 i2c_new_device 为其实例化 一个 i2c_client。在驱动加载的时候遇到同名的 i2c_board_info 就会将 i2c_client 和 driver 绑 定,并且执行 driver 的 probe 函数。 这种方式一般放在平台的代码中。 struct i2c_board_info : /**
方式三:
如果连 i2c 设备的地址不知道,我们可以提供一个地址列表供系统探测。 使用 drivers/media/pci/bt8xx/bttv-input.c 举例: /* Instantiate the I2C IR receiver device, if present */ void init_bttv_i2c_ir(struct bttv *btv) {
方式二:
使用 arch/arm/mach-ux500/board-mop500-uib.c 举例: void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, unsigned n) { struct i2c_adapter *adap; struct i2c_client *client; int i; /* 获得一个总线,当然必须知道我们设备要挂载在哪个总线上,busnum 就是总线编号 */ adap = i2c_get_adapter(busnum); if (!adap) { pr_err("failed to get adapter i2c%d\n", busnum); return; } for (i = 0; i < n; i++) { /* 将 i2c_board_info 所描述的器件与适配器进行关联,并实例化 i2c_client */ client = i2c_new_device(adap, &info[i]); if (!client) pr_err("failed to register %s to i2c%d\n", info[i].type, busnum); } /* 与 i2c_get_adapter 对应,释放资源 */ i2c_put_adapter(adap); } 别忘了在注销驱动或者出错的情况下调用 i2c_unregister_device(struct i2c_client *client) 去释放资源。 这种方式与方式一的差别是不需要在编译内核的时候就要知道设备挂载哪个总线上、 设 备的地址是什么。灵活性变强了。
* as could the init code for each daughtercard in a board stack. * * The I2C devices will be created later, after the adapter for the relevant * bus has been registered. After that moment, standard driver model tools * are used to bind "new style" I2C drivers to the devices. The bus number * for any device declared using this routine is not available for dynamic * allocation. * * The board info passed can safely be __initdata, but be careful of embedded * pointers (for platform_data, functions, etc) since that won't be copied. */ int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len) { int status; down_write(&__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); } up_write(&__i2c_board_lock); return status; }
相关主题