前两篇我们分析了I2C总体框架、I2C总线,本节主要分析下I2C ADAPTER部分,其实也就是
I2C控制器部分。在I2C模块中,有两个设备类型:i2c adapter、i2c client,其中i2c client可以理解为设备驱动模型中的设备,与注册到总线上的i2c驱动绑定,而i2c adapter也属于注册到i2c总线上的设备,但其不需要与i2c驱动绑定。其主要为i2c驱动提供访问i2c设备的方法,同时一个i2c设备需要依附于i2c adapter(在设备模型中,i2c adapter是依附于其上的i2c client的父device)。
本章我们主要说明i2c adapter的注册、注销、i2c adapter提供的方法等。I2c adapter相关的
结构体之前已经介绍,此处不再赘述。
I2c adapter的方法(或i2c adapter的算法)
I2c adapter的方法用于设置该adapter的传输方法、支持的传输模式选择等,对应的结构体为i2c_algorithm,该结构体的定义如下,主要内容如下:
- 若该adapter支持i2c传输方式,则该adapter需要实现master_xfer接口,用以支持通过i2c时序传输数据(读写),
- 若该adapter支持smbus传输方式,则该adapter需要实现smbus_xfer接口,用以支持通过smbus时序传输数据,若不支持smbus传输方式,则通过master_xfer模拟smbus时序实现数据通信。
- functionality接口主要用于返回该adapter支持的方法,如支持I2C_FUNC_I2C、I2C_FUNC_10BIT_ADDR、I2C_FUNC_SMBUS_EMUL等,当调用某一个adapter的通信方法前,需先调用该functionality接口,获取该adapter支持的通信方式等。
/*
* The following structs are for those who like to implement new bus drivers:
* i2c_algorithm is the interface to a class of hardware solutions which can
* be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
* to name two of the most common.
*/
struct i2c_algorithm {
/* If an adapter algorithm can't do I2C-level access, set master_xfer
to NULL. If an adapter algorithm can do SMBus access, set
smbus_xfer. If set to NULL, the SMBus protocol is simulated
using common I2C messages */
/* master_xfer should return the number of messages successfully
processed, or a negative value on error */
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data);
/* To determine what the adapter supports */
u32 (*functionality) (struct i2c_adapter *);
};
如下为i2c imx adapter的方法定义,该i2c adpater支持i2c的通信方法,且支持smbus时序的通信方式,但是使用i2c的通信方法模拟smbus时序通信。
static u32 i2c_imx_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm i2c_imx_algo = {
.master_xfer = i2c_imx_xfer,
.functionality = i2c_imx_func,
};
i2c_adapter注册
I2c adapter的注册主要实现的功能也比较明晰,主要实现如下几个方面的内容:
- 首先判断i2c adapter的各成员是否设置合理(如是否设置成员变量)
- 设置i2c_adapter的device类型的成员变量dev,设置dev的type为i2c_adapter_type,此处设置i2c_adapter_type的目的用于与i2c client进行区分,因i2c client、i2c adaper均需要注册到i2c_bus上,而在i2c_bus模块仅i2c_client、i2c_driver才能进行绑定操作,此处设置dev的type就是防止将i2c adapter与i2c_driver进行匹配。
i2c_adapter_type中定义了一个adpater所支持的默认属性(对应于sysfs下对应adapter目录下的属性文件)以及定义的release方法
- 设置的i2c_adapter所属的bus为i2c_bus;
- 针对每一个注册到i2c总线上的驱动,在该adapter上进行i2c设备的探测,并对探测到的i2c设备进行绑定操作。
此处涉及i2c设备注册的一种方式:针对spd(存储内存模型相关信息的eeprom设备)、hwmon等类的设备,可以在内核初始化时进行i2c设备的注册操作,而在i2c
adapter注册或者相应i2c driver注册时,通过i2c driver的detect函数指针以及i2c driver支持的i2c地址列表信息,自动完成i2c client的探测,并将探测到的i2c client注册到i2c总线上。
但针对这一种i2c设备的注册方式有几个前提条件:
- I2c driver需要支持detect函数;
- I2c adapter与i2c driver均需要标注其支持自动探测i2c设备的类,且它们支持的类型存在交集时方可支持探测(如均标注支持hwmon、spd的探测等)
仅在满足上述两个条件的情况下,才能够支持此类i2c设备的注册。
i2c_adapter的流程图如下所示
i2c_verify_adapter
该接口用于判断注册到i2c总线上的一个设备是否为adapter设备,主要是判断该adpater对应device类型的成员变量dev的type成员是否为i2c_adapter_type。
struct i2c_adapter *i2c_verify_adapter(struct device *dev)
{
return (dev->type == &i2c_adapter_type)
? to_i2c_adapter(dev): NULL;
}
i2c_del_adapter
该接口用于从i2c总线上删除一个adpater,该接口实现的功能大致如下:
- 遍历注册到i2c总线上的所有驱动,针对驱动上已绑定的所有i2c client,完成i2c client的注销操作(包括调用设备驱动模型中的device_unregister进行注销等);
- 针对所有通过应用层sysfs中的接口创建的client设备,也完成i2c client的注销操作
- 调用device_unregister操作,完成该adapter的注销操作。针对i2c部分的注销操作,也就是去除下图中的关联,并将所有依附至该adapter上的i2c client,均进行注销操作。
以上便是i2c adpater相关的注册与注销部分的介绍。下一篇分析i2c client、i2c driver的注销。