接着上一节,看咱们的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";
{
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);
qup_io = request_mem_region(qup_mem->start, resource_size(qup_mem),pdev->name);
/*如果该标志没有设置,则取出相应的资源*/
if (!pdata->use_gsbi_shared_mode) {
if (!pdata->use_gsbi_shared_mode) {
{
gsbi_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gsbi_qup_i2c_addr");
}
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);
}
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;
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);
} ;
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->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;
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);
disable_irq(dev->err_irq);
/*把该dev挂载到dev->adapter的私有数据结构的driver data上*/
i2c_set_adapdata(&dev->adapter, dev);
i2c_set_adapdata(&dev->adapter, dev);
/*设置该adapter的algo算法结构*/
dev->adapter.algo = &qup_i2c_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总线所支持的功能
};
.master_xfer = qup_i2c_xfer,//这是具体的控制器传输方法
.functionality = qup_i2c_func,//返回该I2C总线所支持的功能
};
/*为该adapter的name赋值*/
strlcpy(dev->adapter.name,"QUP I2C adapter",sizeof(dev->adapter.name));
strlcpy(dev->adapter.name,"QUP I2C adapter",sizeof(dev->adapter.name));
/*为该adapter的编号赋值*/
dev->adapter.nr = pdev->id;
dev->adapter.nr = pdev->id;
/*为该控制器的配置gpio*/
pdata->msm_i2c_config_gpio(dev->adapter.nr, 1);
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);
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的注册。