首页 > 其他分享 >IMX平台I2C总线驱动模型

IMX平台I2C总线驱动模型

时间:2023-02-20 21:45:59浏览次数:33  
标签:i2c adapter 总线 dev i2cdev IMX I2C 适配器

i2c adapter——I2C适配器

在i2c总线结构中,i2c adapter对应着真实的物理设备i2c适配器。
i2c-imx.c是I2C适配器的平台总线驱动,文件中包含了对I2C适配器注册和操作的函数,
第一步,将adapter驱动注册到platform总线上——i2c_adap_imx_init调用platform_driver_register,将i2x_imx_driver注册到platform_bus_type,即平台总线上。

//i2c-imx.c
static int __init i2c_adap_imx_init(void)
{
	return platform_driver_register(&i2c_imx_driver);
}

第二步,将i2c设备注册到platform总线上——在设备树中,SOC内部的I2C 适配器设备有相关代码,在解析设备树后,会注册到platform总线上。

//imx7ull.dtsi
            i2c1: i2c@021a0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
                reg = <0x021a0000 0x4000>;
                interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_I2C1>;
                status = "disabled";
            };

            i2c2: i2c@021a4000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
                reg = <0x021a4000 0x4000>;
                interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_I2C2>;
                status = "disabled";
            };

第三步,i2c_imx平台总线驱动调用probe函数。
i2c_add_numbered_adapter用来静态声明一个i2c adapter,通常用在SOC或系统主板上的i2c 适配器,其总线号必须静态指定。反之则会调用i2c_add_adapter来注册一个i2c adapter。

//i2c-imx.c
static int i2x_imc_probe(struct platform_device *pdev*)
{
	...
	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
	...
}

i2c_add_numbered_adapter调用i2c_register_adapter向i2c总线上注册一个adapter。

static int i2c_register_adapter(struct i2c_adapter *adap*)
{
	...
	//指定了adapter的成员struct device dev的名字为i2c-%d
	dev_set_name(&adap->dev, "i2c-%d", adap->nr);
	//指定要注册到i2c设备总线
	adap->dev.bus = &i2c_bus_type;
	adap->dev.type = &i2c_adapter_type;
	res = device_register(&adap->dev);
	...
}

对于上一段代码有两点需要注意:

  1. i2c_bus_type是在i2c-core中的全局变量,类型为struct bus_type,它就代表了i2c设备总线。
  2. 至此,在设备总线i2c_bus_type上面就成功注册了SOC自带的i2c adapter。这时我们在文件系统中还看不到任何的设备节点文件。

    小结:
    i2c-imx平台总线驱动将SOC自带的I2C适配器注册到平台总线上,与设备树提供的设备匹配上后,将i2c适配器注册到了i2c总线上。这时,i2c总线上仅仅有i2c设备,而没有i2c驱动。
    下面介绍i2c驱动。

I2C适配器的通用驱动——i2c-dev

i2c-dev驱动如何创建i2c adapter设备的

i2c-dev.c 是i2c设备驱动文件,使用字符设备的接口。

static int __init i2c_dev_init(void)
{
	...
	/* Keep track of adapters which will be added or removed later */
	res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
	...
	/* Bind to already existing adapters right away */
	i2c_for_each_dev(NULL, i2cdev_attach_adapter);
	...
}

i2c_dev_init函数使用两种方法来保证i2c适配器设备可以被正确创建:
第一种方法:bus_register_notifier,通过注册通知时间,当有i2c设备从总线上添加或删除时,就会通知总线的相关回调函数。
第二种方法:i2c_for_each_dev调用bus_for_each_dev,遍历i2c_bus_type,即i2c总线上的所有i2c适配器,调用回调函数i2cdev_attach_adapter。
i2cdev_attach_adapter函数以字符设备驱动的方法创建相关的i2c适配器设备,代码如下:

static int i2cdev_attach_adapter(struct device *dev, void*dummy)
{
	...
	cdev_init(&i2c_dev->cdev, &i2cdev_fops);
	...
	res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);
	...
	i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
				     MKDEV(I2C_MAJOR, adap->nr), NULL,
				     "i2c-%d", adap->nr);
	...
}


小结:
至此,i2c-dev作为i2c设备驱动创建了设备节点文件,注册了对i2c-dev设备的操作方法,即i2cdev_fops。
在设备中生成了设备节点

[root@imx6ull:/]# ls /sys/class/i2c-dev/
i2c-0  i2c-1

如何通过i2c-dev驱动来操作i2c设备?

在i2cdev_fops中注册了设备操作的回调函数,可以参考字符设备驱动模型。代码如下:

static const struct file_operations i2cdev_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.read		= i2cdev_read,
	.write		= i2cdev_write,
	.unlocked_ioctl	= i2cdev_ioctl,
	.open		= i2cdev_open,
	.release	= i2cdev_release,
};

要注意到的是i2c-dev驱动对应的设备是i2c适配器,以i2cdev_read为例
i2cdev_read调用i2c_master_recv,i2c_master_recv又会调用i2c_transfer函数,i2c_transfer最终调用adap->algo->master_xfer。
master_xfer是i2c_adapter成员i2c_algorithm的成员,它表示了i2c适配器传输数据的方式。代码如下:

static struct i2c_algorithm i2c_imx_algo = {
	.master_xfer	= i2c_imx_xfer,
	.functionality	= i2c_imx_func,
};

其中的master_xfer在文件中有相关实现,这里不再列出,而functionality则代表设备支持的i2c通讯的物理信号上支持的一些特点。
i2c-tool工具就是使用了i2c-dev的ioctl接口实现信息的发送

标签:i2c,adapter,总线,dev,i2cdev,IMX,I2C,适配器
From: https://www.cnblogs.com/ixbwer/p/17139038.html

相关文章