今天我们先来把驱动的框架搭好
首先是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 *);
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;
};
成员非常多,但是目前我们需要的其实只有下面这几个
int (*probe)(struct i2c_client *, const struct i2c_device_id *);//匹配到设备后调用
int (*remove)(struct i2c_client *);//与probe成对使用,注销时调用
struct device_driver driver;//用于匹配设备
const struct i2c_device_id *id_table;//用于匹配设备
而其中的 driver 和 id_table 就与我们之前在设备树中MPU6050的信息匹配起来。
接着我们来看看注册和销毁i2c驱动的两个API。
int i2c_add_adapter(struct i2c_adapter * adapter);//注册
void i2c_del_adapter(struct i2c_adapter * adap);//销毁
有了这些内容,我们就能搭建出一个基本框架了
#include
#include
#include
#include
#include
#include /* for struct device */
#include /* for completion */
#include
#include /* for struct device_node */
#include /* for swab16 */
#include
/*
做一个i2c 的驱动
*/
struct dev_desc mpu6050_dev_desc={
.name = "mpu6050_drv",
};
static const struct of_device_id mpu6050_of_match[] = {
{ .compatible = "InvenSense,mpu6050" },
{},
};
const struct i2c_device_id mpu6050_id_table[] = {
{ "mpu6050", 0 },
{},
};
static int mpu6050_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
printk("-----------%s-----------\n", __FUNCTION__);
return 0;
}
int mpu6050_remove(struct i2c_client *client)
{
printk("-----------%s-----------\n", __FUNCTION__);
return 0;
}
struct i2c_driver mpu6050_drv =
{
.probe = mpu6050_probe,
.remove = mpu6050_remove,
.driver= {
.name = "mpu6050_drv",//sys/bus/i2c/driver
.of_match_table = of_match_ptr(mpu6050_of_match),
},
.id_table = mpu6050_id_table,
};
static int __init i2cdrv_init(void)
{
printk("-----------%s-----------\n", __FUNCTION__);
return i2c_register_driver(THIS_MODULE, &mpu6050_drv);
}
static void __exit i2cdrv_exit(void)
{
printk("-----------%s-----------\n", __FUNCTION__);
i2c_del_driver(&mpu6050_drv);
}
module_init(i2cdrv_init);
module_exit(i2cdrv_exit);
MODULE_LICENSE("GPL");
先编译生成.ko文件放在板子上跑一下,检测能不能正常运行。
[root@farsight ]# insmod iic_drv.ko
[ 10.210000] -----------i2cdrv_init-----------
[root@farsight ]# ls /sys/bus/i2c/drivers/mpu6050_drv/
bind module uevent unbind
[root@farsight ]# ls /sys/bus/i2c/drivers/mpu6050_drv/module/drivers/
i2c:mpu6050_drv
这样就表示我们的框架已经成功在匹配到了设备上。