对于i2c设备的注册过程,首先在/arch/arm/mach_msm的相关目录下面有这样的i2c_board_info结构
在static void __init es209ra_init(void)中有这样一个
函数初始化函数
i2c_register_board_info(0, msm_i2c_board_info,ARRAY_SIZE(msm_i2c_board_info));
这个函数相当于就会去注册i2c设备信息实现如下
int __init
i2c_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;
}
而参数 msm_i2c_board_info由如下过程组成:
=====================================================
/**
* 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
* @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 "new style" I2C drivers. 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;
int irq;
};
=====================================================
static struct i2c_board_info msm_i2c_board_info[] __initdata = {
{
I2C_BOARD_INFO("tps65023", 0x48),
},
#ifdef CONFIG_MAX17040_FUELGAUGE
{
I2C_BOARD_INFO("max17040_fuel_gauge", 0x36),
.platform_data = &max17040_platform_data,
},
#endif
{
I2C_BOARD_INFO("lv5219lg", 0x74),
},
#ifdef CONFIG_SENSORS_AK8973
{
I2C_BOARD_INFO("akm8973", 0x1C),
.platform_data = &akm8973_platform_data,
},
#endif
{
I2C_BOARD_INFO("bma150", 0x38),
.irq = INT_ES209RA_GPIO_ACCEL,
},
{
I2C_BOARD_INFO("semc_imx046_camera", 0x1F),
.irq = INT_ES209RA_GPIO_CAM_ISP,
},
};
上面申请这个数组表示i2c总线上面有这么些设备,包含驱动名称,从地址地址,中断号什么的,还有私有数据结构
上面有六个i2c设备,我们以akm8973分析:
针对I2C_BOARD_INFO("akm8973", 0x1C),
/**
* I2C_BOARD_INFO - macro used to list an i2c device and its address
* @dev_type: identifies the device type
* @dev_addr: the device's address on the bus.
*
* This macro initializes essential fields of a struct i2c_board_info,
* declaring what has been provided on a particular board. Optional
* fields (such as associated irq, or device-specific platform_data)
* are provided using conventional syntax.
*/
#define I2C_BOARD_INFO(dev_type, dev_addr) \
.type = (dev_type), .addr = (dev_addr)
.platform_data = &akm8973_platform_data,
static struct akm8973_i2c_platform_data akm8973_platform_data = {
.gpio_config = ak8973_gpio_config,
.xres = ak8973_xres
};
========================================================================================
现在回到函数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);
}
阅读(3315) | 评论(0) | 转发(0) |