1.内核中I2C相关代码可以分为以下三个层次:
(1)I2C主体框架.由i2c.h和i2c-core.c构成,它提供了核心数据结构定义,适配器驱动和设备驱动的注册,注销管理.
(2)I2C总线适配器驱动.定义描述总线适配器的i2c_adapter数据结构,实现在具体i2c适配上的i2c总线通信方法,它是由i2c_algorithm数据结构进行描述的.
(3)
I2C设备驱动:定义描述具体设备的i2c_client和可能的么有数据结构,借助i2c框架的i2c_probe函数实现注册设备的
attach_adapter方法,提供设备可能使用的地址范围,以及设备地址检测成功后创建i2c_client数据结构回调函数.
2. I2C设备驱动程序中重要的几个数据结构.
(1)这是一个与Linux下所有设备驱动都相关的数据结构.
struct device_driver {
char * name;
struct bus_type * bus;
struct completion unload_done;
struct kobject kobj;
struct list_head devices;
struct module * owner;
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev, u32 state, u32 level);
int (*resume) (struct device * dev, u32 level);
};
(2)attach_adapter
回调函数在安装i2c启程驱动程序模块时,或者在安装i2c适配器驱动程序模块时被调用,用于检测,认领设备并为设备分配i2_client及相应的私有
数据结构;而detach_client即是用来释放上面两个函数即创建的私有数据结构.
/*
* A driver is capable of handling one or more physical devices present on
* I2C adapters. This information is used to inform the driver of adapter
* events.
*/
struct i2c_driver {
struct module *owner;
char name[32];
int id;
unsigned int class;
unsigned int flags; /* div., see below */
/* Notifies the driver that a new bus has appeared. This routine
* can be used by the driver to test if the bus meets its conditions
* & seek for the presence of the chip(s) it supports. If found, it
* registers the client(s) that are on the bus to the i2c admin. via
* i2c_attach_client.
*/
int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);
/* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private data. Also, if the client struct
* has been dynamically allocated by the driver in the function above,
* it must be freed here.
*/
int (*detach_client)(struct i2c_client *);
/* 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;
struct list_head list;
};
(3)attach_adapter
回调函数在安装i2c启程驱动程序模块时,或者在安装i2c适配器驱动程序模块时被调用,用于检测,认领设备并为设备分配i2_client及相应的私有
数据结构;而detach_client即是用来释放上面两个函数即创建的私有数据结构.
struct i2c_client {
int id;
unsigned int flags; /* div., see below */
unsigned int addr; /* chip address NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits of this char */
/* addr:
unsigned int to make lm_sensors i2c-isa adapter work more cleanly. It
does not take any more memory space, due to alignment considerations */
struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */
int usage_count; /* How many accesses currently */
/* to the client */
struct device dev;/* the device structure */
struct list_head list;
char name[I2C_NAME_SIZE];
struct completion released;
};
3.下面用tlv320aic33驱动程序来大概说一下整个过流程:
(1)先定义i2c_driver和i2c_client这两个数据结构.然后用面这个函数来初始化这个数据结构.
static int
aic33_i2c_init(void)
{
int err;
struct i2c_driver *driver = &aic33_i2c_dev.driver;
driver->owner = THIS_MODULE;
strlcpy(driver->name, "Audio Codec I2C driver", sizeof(driver->name));
driver->id = I2C_DRIVERID_EXP0;
driver->flags = I2C_DF_NOTIFY;
driver->attach_adapter = aic33_i2c_probe_adapter;
driver->detach_client = aic33_i2c_detach_client;
err = i2c_add_driver(driver);
if (err) {
printk(KERN_ERR "Failed to register Audio Codec I2C client.\n");
return err;
}
return 0;
}
阅读(941) | 评论(0) | 转发(0) |