I2C子系统驱动架构 - 驱动框架
文章系列
基于linux内核4.6.3版本介绍
I2C驱动框架
I2C驱动框架图如下所示,用户空间上的节点是用于上层开发工程师来操作i2c设备,内核空间的驱动架构分2层,Bus层的驱动代码是芯片厂商已经写好的,对于驱动开发人员来说,主要是设计device层的代码,不过要理解i2c驱动框架对于整个框架机制还是要熟练的
上图中的设备节点/dev/i2c-*只是简单列举了例子中i2c_dev.c驱动中的设备节点,实际i2c设备驱动节点的例子不一定是上图所示。不管怎样,整个i2c驱动框架还是符合设备驱动模型device-bus-driver,上图中的Device层的含义是相对于i2c Bus层来理解的,每一层都有自己的注册方法,系统启动后先要把Bus层注册,一个adapter对应一个bus,然后再把挂在总线上的所有device进行注册,然后i2c driver进行注册找到匹配的device,这样一个i2c设备就完成了。
i2c驱动的代码都在目录drivers/i2c/下,有三个目录algos busses muxes,其中busses目录是每个i2c模块或者说总线的代码目录,drivers/i2c/下的文件i2c-boardinfo.c i2c-core.c i2c-core.h i2c-dev.c i2c-mux.c i2c-smbus.c i2c-stub.c都是i2c驱动架构文件,其中 i2c-core.c 是主要文件
I2C总线介绍
I2C总线设备的注册是通过platform总线来注册初始化的,在系统初始化的时候platform总线会完成i2c bus也就是i2c adapter的device的注册,然后driver的注册根据各个SoC的i2c模块来进行注册,注册代码在文件drivers/i2/busses/i2c-*.c中,注册后就会进行匹配,匹配成功就完成adapter的注册,adapter除了可以被i2c_client使用,也可以被其他使用了i2c总线的设备来使用,比如在v4l2中就有v4l2_subdev是使用的i2c adapter作为subdev
结构体介绍
i2c_adapter和i2c_algorithm 都是操作i2c bus的结构体,前者定义一个i2c模块,后者定义操作模块的方法
struct i2c_adapter {
struct module *owner;
unsigned int class; /* classes to allow probing for */
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
void *algo_data;
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
int timeout; /* in jiffies */
int retries;
struct device dev; /* the adapter device */
int nr;
char name[48];
struct completion dev_released;
struct mutex userspace_clients_lock;
struct list_head userspace_clients;
struct i2c_bus_recovery_info *bus_recovery_info;
const struct i2c_adapter_quirks *quirks;
};
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 *);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
int (*reg_slave)(struct i2c_client *client);
int (*unreg_slave)(struct i2c_client *client);
#endif
};
函数介绍
i2c_add_adapter和i2c_add_numbered_adapter用来注册i2c bus设备,并把挂载在总线上的设备进行注册
i2c_del_adapter用来卸载i2c bus设备
extern int i2c_add_adapter(struct i2c_adapter *);
extern void i2c_del_adapter(struct i2c_adapter *);
extern int i2c_add_numbered_adapter(struct i2c_adapter *);
I2C设备驱动介绍
结构体介绍
i2c_client 等同于驱动模型中的device
struct i2c_client {
unsigned short flags; /* div., see below */
unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
char name[I2C_NAME_SIZE];
struct i2c_adapter *adapter; /* the adapter we sit on */
struct device dev; /* the device structure */
int irq; /* irq issued by device */
struct list_head detected;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
i2c_slave_cb_t slave_cb; /* callback for slave mode */
#endif
};
i2c_driver 等同于驱动模型中的driver
struct i2c_driver {
unsigned int class;
/* Notifies the driver that a new bus has appeared. You should avoid
* using this, it will be removed in a near future.
*/
int (*attach_adapter)(struct i2c_adapter *) __deprecated;
/* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *);
/* Alert callback, for example for the SMBus alert protocol.
* The format and meaning of the data value depends on the protocol.
* For the SMBus alert protocol, there is a single bit of data passed
* as the alert response's low bit ("event flag").
*/
void (*alert)(struct i2c_client *, unsigned int data);
/* a ioctl like command that can be used to perform specific functions
* with the device.
*/
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
struct device_driver driver;
const struct i2c_device_id *id_table;
/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, struct i2c_board_info *);
const unsigned short *address_list;
struct list_head clients;
};
函数介绍
i2c_new_device和i2c_unregister_device等同于驱动模型中的device注册与卸载函数
extern struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
extern struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info,
unsigned short const *addr_list,
int (*probe)(struct i2c_adapter *, unsigned short addr));
extern struct i2c_client *
extern void i2c_unregister_device(struct i2c_client *);
i2c_register_driver和i2c_del_driver等同于驱动模型中的driver注册与卸载函数
extern int i2c_register_driver(struct module *, struct i2c_driver *);
extern void i2c_del_driver(struct i2c_driver *);
更多推荐
所有评论(0)