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

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

方式三:
如果连 i2c 设备的地址不知道,我们可以提供一个地址列表供系统探测。 使用 drivers/media/pci/bt8xx/bttv-input.c 举例: /* Instantiate the I2C IR receiver device, if present */ void init_bttv_i2c_ir(struct bttv *btv) {
* struct i2c_board_info - template for device creation * @type: chip type, to initialize i2c_client.name * @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,
Linux I2C(一)之常用的几种实例化 (i2c_client )
http://blog.csdn.net/lБайду номын сангаасgandong/article/details/48092397 前言:
因为工作是音频驱动,所以经常涉及到 I2C、I2S 等常用的总线,想将 I2C 相关的东西 总结一下,让自己更加了解 I2C。
方式二:
使用 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) 去释放资源。 这种方式与方式一的差别是不需要在编译内核的时候就要知道设备挂载哪个总线上、 设 备的地址是什么。灵活性变强了。
方式一:
使用 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 : /**
/* 这里就是地址列表 */ const unsigned short addr_list[] = { 0x1a, 0x18, 0x64, 0x30, 0x71, I2C_CLIENT_END }; struct i2c_board_info info; struct i2c_client *i2c_dev; if (0 != btv->i2c_rc) return; /* 用于存放 i2c_board_info 信息 */ memset(&info, 0, sizeof(struct i2c_board_info)); memset(&btv->init_data, 0, sizeof(btv->init_data)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); switch (btv->c.type) { case BTTV_BOARD_PV951: btv->init_data.name = "PV951"; btv->init_data.get_key = get_key_pv951; btv->init_data.ir_codes = RC_MAP_PV951; info.addr = 0x4b; break; } if (btv->init_data.name) { info.platform_data = &btv->init_data; i2c_dev = i2c_new_device(&btv->c.i2c_adap, &info); } else { /* * The external IR receiver is at i2c address 0x34 (0x35 for * reads). Future Hauppauge cards will have an internal * receiver at 0x30 (0x31 for reads). In theory, both can be * fitted, and Hauppauge suggest an external overrides an * internal. * That's why we probe 0x1a (~0x34) first. CB */ /* 这样就会在指定的总线上匹配 addr_list 中地址,将第一个匹配正确的地址保存 到 info->addr,然后使用 i2c_device_new 来实例化 i2c_client */ i2c_dev = i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL); } if (NULL == i2c_dev) return; #if defined(CONFIG_MODULES) && defined(MODULE)
* 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; }
相关文档
最新文档