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

接着上一节,看咱们的probe函数,代码还是只看主线。代码很长,两个字:淡定。
static int __devinit qup_i2c_probe(struct platform_device *pdev)
{
 struct qup_i2c_dev *dev;
 struct resource   *qup_mem, *gsbi_mem, *qup_io, *gsbi_io;
 struct resource   *err_irq;
 struct clk         *clk, *pclk;
 struct msm_i2c_platform_data *pdata;
 const char *qup_apps_clk_name = "qup_clk";
 pdata = pdev->dev.platform_data;//取出平台设备的platform_data
 /*通过名字取出在BSP文件中注册的相应资源*/
 qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,"qup_phys_addr");
 err_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,"qup_err_intr");
 
/*请求资源,告诉其他驱动,该资源已经被占用*/
 qup_io = request_mem_region(qup_mem->start, resource_size(qup_mem),pdev->name);
 
 /*如果该标志没有设置,则取出相应的资源*/
 if (!pdata->use_gsbi_shared_mode) {
  {
  gsbi_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gsbi_qup_i2c_addr");
  }
 
  /*请求该内存资源*/
  gsbi_io = request_mem_region(gsbi_mem->start,resource_size(gsbi_mem),pdev->name);
 }
 
 /*如果该clk不为空,通过名字取出该clk*/
 if (pdata->clk != NULL)
  qup_apps_clk_name = pdata->clk;
  clk = clk_get(&pdev->dev, qup_apps_clk_name);
 }
 
 
 /*如果该pclk不为空,通过名字取出该clk*/
 if (pdata->pclk != NULL) {
  pclk = clk_get(&pdev->dev, pdata->pclk);
  } ;
 
 /*分配qup_i2c_dev结构体*/
 dev = kzalloc(sizeof(struct qup_i2c_dev), GFP_KERNEL);
 dev->dev = &pdev->dev;
 dev->err_irq = err_irq->start;
 dev->num_irqs = 1;
 dev->clk = clk;
 dev->pclk = pclk;
 
 /*映射请求到的内存*/
 dev->base = ioremap(qup_mem->start, resource_size(qup_mem));

 /* Configure GSBI block to use I2C functionality */
 if (gsbi_mem) {
  dev->gsbi = ioremap(gsbi_mem->start, resource_size(gsbi_mem));
 }
 
 /*初始化完dev后,把dev设置为pdev的dev的私有数据*/
 platform_set_drvdata(pdev, dev);
 
 dev->one_bit_t = USEC_PER_SEC/pdata->clk_freq;
 dev->pdata = pdata;
 dev->clk_ctl = 0;
 dev->pos = 0;
 
 /*请求中断,并且设置中断处理函数*/
 ret = request_irq(dev->err_irq, qup_i2c_interrupt,IRQF_TRIGGER_HIGH, "qup_err_intr", dev);
 
 /*去使能该中断*/
 disable_irq(dev->err_irq);
 
 /*把该dev挂载到dev->adapter的私有数据结构的driver data上*/
 i2c_set_adapdata(&dev->adapter, dev);
 
 /*设置该adapter的algo算法结构*/
 dev->adapter.algo = &qup_i2c_algo;
其中该结构的初始化实例如下:
static const struct i2c_algorithm qup_i2c_algo = {
 .master_xfer = qup_i2c_xfer,//这是具体的控制器传输方法
 .functionality = qup_i2c_func,//返回该I2C总线所支持的功能
};
 
 /*为该adapter的name赋值*/
 strlcpy(dev->adapter.name,"QUP I2C adapter",sizeof(dev->adapter.name));
 
 /*为该adapter的编号赋值*/
 dev->adapter.nr = pdev->id;
 
 /*为该控制器的配置gpio*/
 pdata->msm_i2c_config_gpio(dev->adapter.nr, 1);
 
 /*初始化dev的部分变量*/
 dev->suspended = 0;
 mutex_init(&dev->mlock);
 dev->clk_state = 0;
 setup_timer(&dev->pwr_timer, qup_i2c_pwr_timer, (unsigned long) dev);
 
 /*把该adapter加入到系统中*/
 ret = i2c_add_numbered_adapter(&dev->adapter);
}
总结下:探测函数所做的工作就是,初始化dev,并把把该dev挂载到dev->adapter的私有数据结构的driver data上,然后设置adapter,把该adapter加入到系统中。下面的文章主要关注adapter的注册。

你可能感兴趣的:(基于高通MSM 8x60的I2C驱动终极讲解(8))