目录
i2c设备驱动结构体
I2C 设备驱动要使用i2c_driver和i2c_client数据结构并填充其中的成员函数。i2c_client 一般被包含在设备的私有信息结构体yyy_data 中,而i2c_driver 则适合被定义为全局变量并初始化,i2c_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").
* For the SMBus Host Notify protocol, the data corresponds to the
* 16-bit payload data reported by the slave device acting as master.
*/
void (*alert)(struct i2c_client *, enum i2c_alert_protocol protocol,
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;
};
结构体重一共有四个变量比较重要:
struct device_driver driver:驱动实例
int (*probe)(struct i2c_client *, const struct i2c_device_id *):当驱动和设备匹配之后会调用此函数进行初始化
int (*remove)(struct i2c_client *):probe的对立函数,完成驱动的去初始化工作
const struct i2c_device_id *id_table:支持的驱动列表
以drivers\media\dvb-frontends\af9033.c为例
i2c_driver结构体初始化如下所示:
static struct i2c_driver af9033_driver = {
.driver = {
.name = "af9033",
.suppress_bind_attrs = true,
},
.probe = af9033_probe,
.remove = af9033_remove,
.id_table = af9033_id_table,
};
模块的加载和卸载
定义的i2c_driver需要通过函数i2c_add_driver将i2c_driver注册到linux系统中,需要通过函数i2c_del_driver从linux中卸载i2c_driver驱动。函数由i2c核心提供。
添加驱动方法如下所示:
static int __init af9033_i2c_init(void)
{
return i2c_add_driver(&af9033_driver);
}
module_init(af9033_i2c_init);
static void __exit af9033_i2c_exit(void)
{
i2c_del_driver(&af9033_driver);
}
module_exit(af9033_i2c_exit);
或者直接使用宏添加驱动
module_i2c_driver(af9033_driver);
I2C通信模板
添加完设备驱动之后就可以直接使用i2c进行通信了,通信模板如下所示:
static int af9033_rd_regs(struct af9033_dev *dev, u32 reg, u8 *val, int len)
{
int ret;
u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff,
(reg >> 0) & 0xff };
struct i2c_msg msg[2] = {
{
.addr = dev->client->addr,
.flags = 0,
.len = sizeof(buf),
.buf = buf
}, {
.addr = dev->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = val
}
};
ret = i2c_transfer(dev->client->adapter, msg, 2);
if (ret == 2) {
ret = 0;
} else {
dev_warn(&dev->client->dev, "i2c rd failed=%d reg=%06x len=%d\n",
ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
}