i2c设备驱动属于字符设备驱动,其构造自然是跟字符设备的结构一样了,字符设备:1、 分配字符设备号(主次设备号),设置为0,表示自动分配设备号
2、构造file_operatios 3、注册设备,register_chrdev(1,2,3),三个参数分别是设备号,名称(不重要,随便起),构造的file_operations。
i2c总线驱动:核心层:提供统一的接口函数。适配器:提供硬件接口,及其硬件i2c接口
i2c的设备驱动模型 i2c_bus_type ,在这个总线上左右挂载分别是i2c_client和i2c_driver的链表,通过各自注册接口进行注册,在i2c_client 和i2c_driver的原型如下
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 i2c_driver *driver; /* and our access routines */
struct device dev; /* the device structure */
int irq; /* irq issued by device */
struct list_head detected;
};
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 *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(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_client 和i2c_driver 两个结构体之间通过name 连接在一起,只有对应的name匹配正确,才能够调用i2c_driver 中的probe函数。例如
实现i2c_dev.c和i2c_drv.c两个文件中实现at24cxx的i2c驱动代码:
一旦这两个文件的at24c8这个名字出现不同,那么这个驱动绝对不会加载成功。
以i2c设备at24c80为例分析i2c代码
1、构造/设置i2c_driver
2、注册i2c_driver
这是实现i2c设备驱动的右边部分,
然后实现根据要求实现i2c_driver中的函数,加入函数出口函数及其部分关键修饰
那么整个i2c_driver就实现了
但是这个实现,编译加载成功后,并没有在设备文件中产生可操作的接口,使用ls /dev/at24c08查看,并没有产生一个设备
这个就需要我们实现左边部分i2c_client\
代码如下
分别为驱动的入口和出口,入口函数at24cxx_dev_init中实现了适配器的分派,大多开发板中的i2c_dev适配器只有i2c-0,所以直接分派适配器即可,
i2c_new_device这是整个程序的核心,只有启动调用它,才会调用函数probe。这个函数的作用主要是强制认为设备存在。所以一旦name匹配,他就
一定能够启动probe函数
和他具有同等功能的还有一个函数:i2c_new_probed_device,区别是,这个函数用于“对于已经识别出来的设备”才会创建,即确定设备是真实存在的。
i2c_put_adapter函数和i2c_get_adapter相对应的函数,它用来释放适配器。
方法二:使用i2c_register_board_info 的板级文件构造i2c设备
方法三:直接在用户空间操作i2c设备。使用open和ioctl函数
方法四:查询所有的adpater