首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

i.mx536(cotex-a8核)的I2C驱动了解一(probe)

2013-02-06 
i.mx536(cotex-a8核)的I2C驱动理解一(probe)//总得来说三个主要步骤//(1)映射虚拟内存,注册中断等//(2)填

i.mx536(cotex-a8核)的I2C驱动理解一(probe)

//总得来说三个主要步骤//(1)映射虚拟内存,注册中断等//(2)填充结构体struct imx_i2c_struct//(3)调用i2c_register_adapter注册I2C设备static int __init i2c_imx_probe(struct platform_device *pdev){//分析了几个驱动发现,平台驱动有很多相似的地方,比如说在prode里一般都会定义//一个platform_data结构体,一个对应设备的结构体比如struct imx_i2c_structstruct imx_i2c_struct *i2c_imx;struct resource *res;struct imxi2c_platform_data *pdata;//__iomem表示指针是指向一个I/O的内存空间void __iomem *base;//resource_size_t = u32resource_size_t res_size;int irq;int ret;dev_dbg(&pdev->dev, "<%s>\n", __func__);//获取IO资源和中断资源res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!res) {dev_err(&pdev->dev, "can't get device resources\n");return -ENOENT;}//获取中断资源irq = platform_get_irq(pdev, 0);if (irq < 0) {dev_err(&pdev->dev, "can't get irq number\n");return -ENOENT;}pdata = pdev->dev.platform_data;if (pdata && pdata->init) {ret = pdata->init(&pdev->dev);if (ret)return ret;}res_size = resource_size(res);//检测该IO资源是否可用,若可用,并标志为已用if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {ret = -EBUSY;goto fail0;}//映射物理地址到虚拟内存base = ioremap(res->start, res_size);if (!base) {dev_err(&pdev->dev, "ioremap failed\n");ret = -EIO;goto fail1;}//给i2c_imx分配内存,并初始化为0i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL);if (!i2c_imx) {dev_err(&pdev->dev, "can't allocate interface\n");ret = -ENOMEM;goto fail2;}//填充结构体i2c_imxstrcpy(i2c_imx->adapter.name, pdev->name);//i2c_adapter,Linux的I2C驱动框架中的主要数据结构(i2c_driver、i2c_client、i2c_adapter和i2c_algorithm)之一出现了//对应于物理上的一个适配器i2c_imx->adapter.owner= THIS_MODULE;//i2c_algorithm也出现了//i2c_algorithm主要提供通信的函数i2c_imx->adapter.algo= &i2c_imx_algo;i2c_imx->adapter.dev.parent= &pdev->dev;i2c_imx->adapter.nr = pdev->id;i2c_imx->irq= irq;i2c_imx->base= base;i2c_imx->res= res;/* Get I2C clock *///开启I2C时钟源i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk");if (IS_ERR(i2c_imx->clk)) {ret = PTR_ERR(i2c_imx->clk);dev_err(&pdev->dev, "can't get I2C clock\n");goto fail3;}/* Request IRQ *///注册中断函数i2c_imx_isrret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx);if (ret) {dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq);goto fail4;}/* Init queue *///初始化queueinit_waitqueue_head(&i2c_imx->queue);/* Set up adapter data *///把I2C_imx保存到adapter中,最终可以调用i2c_get_adapdata获取i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);/* Set up clock divider *///这个pdata->bitrate在板级配置文件中设置if (pdata && pdata->bitrate)i2c_imx_set_clk(i2c_imx, pdata->bitrate);elsei2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);/* Set up chip registers to defaults */writeb(0, i2c_imx->base + IMX_I2C_I2CR);writeb(0, i2c_imx->base + IMX_I2C_I2SR);/* Add I2C adapter *///重要的函数来了,//i2c_add_numbered_adapter最终调用i2c_register_adapter添加I2C控制器ret = i2c_add_numbered_adapter(&i2c_imx->adapter);if (ret < 0) {dev_err(&pdev->dev, "registration failed\n");goto fail5;}/* Set up platform driver data */platform_set_drvdata(pdev, i2c_imx);//打印调试信息dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq);dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",i2c_imx->res->start, i2c_imx->res->end);dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n",res_size, i2c_imx->res->start);dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",i2c_imx->adapter.name);dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");return 0;   /* Return OK */fail5:free_irq(i2c_imx->irq, i2c_imx);fail4:clk_put(i2c_imx->clk);fail3:kfree(i2c_imx);fail2:iounmap(base);fail1:release_mem_region(res->start, resource_size(res));fail0:if (pdata && pdata->exit)pdata->exit(&pdev->dev);return ret; /* Return error number */}

热点排行