基于高通MSM 8x60的I2C驱动终极讲解(10)

来源:互联网 发布:麦可思数据公司 编辑:程序博客网 时间:2024/05/22 17:48

接着上一节讲,板级i2c设备的初始化,板级中的代码如下:就以马达驱动isa1200为例:
先把用到的数据贴出来。
 
/*该马达的平台数据*/
#define PMIC_GPIO_HAP_ENABLE   18  /* PMIC GPIO Number 19 */
static struct isa1200_platform_data isa1200_1_pdata = {
 .name = "vibrator",
 .power_on = isa1200_power,
 .dev_setup = isa1200_dev_setup,
 /*gpio to enable haptic*/
 .hap_en_gpio = PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
 .max_timeout = 15000,
 .mode_ctrl = PWM_GEN_MODE,
 .pwm_fd = {
  .pwm_div = 256,
 },
 .is_erm = false,
 .smart_en = true,
 .ext_clk_en = true,
 .chip_en = 1,
};
 
/*该马达的板级结构*/
static struct i2c_board_info msm_isa1200_board_info[] = {
 {
  I2C_BOARD_INFO("isa1200_1", 0x90>>1),
  .platform_data = &isa1200_1_pdata,
 },
};
 
struct i2c_registry {
 u8                     machs;
 int                    bus;
 struct i2c_board_info *info;
 int                    len;
};
 
#define I2C_FLUID (1 << 4)
#define MSM_GSBI8_QUP_I2C_BUS_ID 3
 
 /*初始化该注册结构*/
static struct i2c_registry msm8x60_i2c_devices[] __initdata = {
  I2C_FLUID,
  MSM_GSBI8_QUP_I2C_BUS_ID,
  msm_isa1200_board_info,
  ARRAY_SIZE(msm_isa1200_board_info),
 }
注册该结构的流程如下:
static void __init msm8x60_init(struct msm_board_data *board_data)
{
  ......
  register_i2c_devices();
  .......
}
static void register_i2c_devices(void)
{
 ...........
 /*循环注册每一个设备*/
 for (i = 0; i < ARRAY_SIZE(msm8x60_i2c_devices); ++i) {
  if (msm8x60_i2c_devices[i].machs & mach_mask)
   i2c_register_board_info(msm8x60_i2c_devices[i].bus,msm8x60_i2c_devices[i].info,
      msm8x60_i2c_devices[i].len);
 }
}
继续看注册函数:
int i2c_register_board_info(int busnum,struct i2c_board_info const *info, unsigned len)
{
 /*更新__i2c_first_dynamic_bus_num*/
 if (busnum >= __i2c_first_dynamic_bus_num)
  __i2c_first_dynamic_bus_num = busnum + 1;
 
 /*为每一个要注册的设备分配一个devinfo,为其赋值,并把它挂到全局链表&__i2c_board_list中*/
 for (status = 0; len; len--, info++) {
  struct i2c_devinfo *devinfo;
  devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
  devinfo->busnum = busnum;
  devinfo->board_info = *info;
  list_add_tail(&devinfo->list, &__i2c_board_list);
 }
 up_write(&__i2c_board_lock);
 return status;
}
上一节最后那个函数会扫描该链表上的结构,前提是该链表上的busnum要和adapter的nr号匹配。
这些资源注册后,继续跟踪上一节没有分析完的部分:
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
 struct i2c_devinfo *devinfo;
 
 /*取出每一个结构,并且用该结构的busnum和adapter的nr进行比较,相等的话,继续处理*/
 list_for_each_entry(devinfo, &__i2c_board_list, list) {
  if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter,&devinfo->board_info))
 }
}
接着看处理的函数:
在分析前,看下一个结构体
struct i2c_client {
 unsigned short flags; 
 unsigned short addr;/*chip address NOTE: 7bit addresses are stored in the _LOWER_ 7 bits*/
 char name[I2C_NAME_SIZE];
 struct i2c_adapter *adapter; /* the adapter we sit on */
 struct i2c_driver *driver;   /* and our access routines */
 struct device dev;           /* the device structure  */
 int irq;                     /* irq issued by device  */
 struct list_head detected;
};
 
下面的函数所做的主要事情是:为每一个在BSP文件注册的i2c_board_info生成一个client设备。
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
 struct i2c_client *client;
 
 /* 分配一个client客户端结构体*/
 client = kzalloc(sizeof *client, GFP_KERNEL);
 
 /*为该结构体各项分别赋值*/
 client->adapter = adap;
 client->dev.platform_data = info->platform_data;
 if (info->archdata)
  client->dev.archdata = *info->archdata;
 client->flags = info->flags;
 client->addr = info->addr;
 client->irq = info->irq;
 strlcpy(client->name, info->type, sizeof(client->name));
 
 /* 检查客户端的地址是否有效*/
 status = i2c_check_client_addr_validity(client);

 /*检查客户端的地址是否被占用*/
 status = i2c_check_addr_busy(adap, client->addr);
 
 /*为client的dev成员赋值*/
 client->dev.parent = &client->adapter->dev;
 client->dev.bus = &i2c_bus_type;
 client->dev.type = &i2c_client_type;
 client->dev.of_node = info->of_node;
 dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),client->addr);
 
 /*注册该dev*/
 status = device_register(&client->dev);
 }

0 0