Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

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

$
0
0
//总得来说三个主要步骤
//(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_struct
	struct imx_i2c_struct *i2c_imx;
	struct resource *res;
	struct imxi2c_platform_data *pdata;
	//__iomem表示指针是指向一个I/O的内存空间
	void __iomem *base;
	//resource_size_t = u32
	resource_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分配内存,并初始化为0
	i2c_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_imx
	strcpy(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_isr
	ret = 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 */
	//初始化queue
	init_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);
	else
		i2c_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 */
}

作者:h32dong809 发表于2013-1-29 22:26:59 原文链接
阅读:78 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>