linux i2c设备驱动

一. i2c的结构体

     1. i2c适配器

  1. struct i2c_adapter {  
  2.     struct module *owner;   //模块所有者  
  3.     unsigned int id __deprecated;  
  4.     unsigned int class//支持的类别(I2C_CLASS_HWMON,I2C_CLASS_DDC,I2C_CLASS_SPD)  
  5.     const struct i2c_algorithm *algo;   //i2c算法结构体  
  6.     void *algo_data;  
  7.     struct rt_mutex bus_lock;  
  8.     int timeout;    //超时值默认是1s  
  9.     int retries;    //通讯重试次数  
  10.     struct device dev;      //设备文件  
  11.     int nr; //id号,次设备号  
  12.     char name[48];  //i2c适配器名  
  13.     struct completion dev_released;  
  14.     struct mutex userspace_clients_lock;  
  15.     struct list_head userspace_clients; //挂接的设备链表头  
  16. };  
struct i2c_adapter {
	struct module *owner;	//模块所有者
	unsigned int id __deprecated;
	unsigned int class;	//支持的类别(I2C_CLASS_HWMON,I2C_CLASS_DDC,I2C_CLASS_SPD)
	const struct i2c_algorithm *algo;	//i2c算法结构体
	void *algo_data;
	struct rt_mutex bus_lock;
	int timeout;	//超时值默认是1s
	int retries;	//通讯重试次数
	struct device dev;		//设备文件
	int nr;	//id号,次设备号
	char name[48];	//i2c适配器名
	struct completion dev_released;
	struct mutex userspace_clients_lock;
	struct list_head userspace_clients;	//挂接的设备链表头
};

     2. i2c设备

  1. struct i2c_client {  
  2.     unsigned short flags;   //标志(读/写)  
  3.     unsigned short addr;    //i2c地址  
  4.     char name[I2C_NAME_SIZE];   //i2c设备名  
  5.     struct i2c_adapter *adapter;    //匹配的i2c适配器  
  6.     struct i2c_driver *driver;      //匹配的i2c驱动  
  7.     struct device dev;      //设备文件  
  8.     int irq;  
  9.     struct list_head detected;  //"检测到"链表头  
  10. };  
struct i2c_client {
	unsigned short flags;	//标志(读/写)
	unsigned short addr;	//i2c地址
	char name[I2C_NAME_SIZE];	//i2c设备名
	struct i2c_adapter *adapter;	//匹配的i2c适配器
	struct i2c_driver *driver;		//匹配的i2c驱动
	struct device dev;		//设备文件
	int irq;
	struct list_head detected;	//"检测到"链表头
};

     3. i2c驱动

  1. struct i2c_driver {  
  2.     unsigned int class;  
  3.     int (*attach_adapter)(struct i2c_adapter *);    //连接i2c适配器  
  4.     int (*detach_adapter)(struct i2c_adapter *);    //分离i2c适配器  
  5.     int (*probe)(struct i2c_client *, const struct i2c_device_id *);    //probe方法  
  6.     int (*remove)(struct i2c_client *); //remove方法  
  7.     void (*shutdown)(struct i2c_client *);  //关闭  
  8.     int (*suspend)(struct i2c_client *, pm_message_t mesg); //挂起  
  9.     int (*resume)(struct i2c_client *); //唤醒  
  10.     void (*alert)(struct i2c_client *, unsigned int data);  
  11.     int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);  
  12.     struct device_driver driver;    //设备驱动文件  
  13.     const struct i2c_device_id *id_table;   //支持的i2c设备id表  
  14.     int (*detect)(struct i2c_client *, struct i2c_board_info *);    //检测  
  15.     const unsigned short *address_list;   
  16.     struct list_head clients;   //匹配的设备链表  
  17. };  
struct i2c_driver {
	unsigned int class;
	int (*attach_adapter)(struct i2c_adapter *);	//连接i2c适配器
	int (*detach_adapter)(struct i2c_adapter *);	//分离i2c适配器
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);	//probe方法
	int (*remove)(struct i2c_client *);	//remove方法
	void (*shutdown)(struct i2c_client *);	//关闭
	int (*suspend)(struct i2c_client *, pm_message_t mesg);	//挂起
	int (*resume)(struct i2c_client *);	//唤醒
	void (*alert)(struct i2c_client *, unsigned int data);
	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
	struct device_driver driver;	//设备驱动文件
	const struct i2c_device_id *id_table;	//支持的i2c设备id表
	int (*detect)(struct i2c_client *, struct i2c_board_info *);	//检测
	const unsigned short *address_list;	
	struct list_head clients;	//匹配的设备链表
};

     4. i2c板级信息

  1. struct i2c_board_info {  
  2.     char        type[I2C_NAME_SIZE];    //设备名  
  3.     unsigned short  flags;  //标志(读/写)  
  4.     unsigned short  addr;   //i2c地址  
  5.     void        *platform_data; //平台资源  
  6.     struct dev_archdata *archdata;  
  7. #ifdef CONFIG_OF   
  8.     struct device_node *of_node;  
  9. #endif   
  10.     int     irq;  
  11. };  
struct i2c_board_info {
	char		type[I2C_NAME_SIZE];	//设备名
	unsigned short	flags;	//标志(读/写)
	unsigned short	addr;	//i2c地址
	void		*platform_data;	//平台资源
	struct dev_archdata	*archdata;
#ifdef CONFIG_OF
	struct device_node *of_node;
#endif
	int		irq;
};

    4.1 i2c板级信息辅助宏(一般声明在板级初始化函数中)

  1. #define I2C_BOARD_INFO(dev_type, dev_addr) \  
  2.     .type = dev_type, .addr = (dev_addr)  
#define I2C_BOARD_INFO(dev_type, dev_addr) \
	.type = dev_type, .addr = (dev_addr)

     5. i2c消息

  1. struct i2c_msg {  
  2.     __u16 addr; //i2c设备地址   
  3.     __u16 flags;    //标志(读/写)   
  4.     __u16 len;  //消息长度   
  5.     __u8 *buf;  //缓冲区   
  6. };  
struct i2c_msg {
	__u16 addr;	//i2c设备地址
	__u16 flags;	//标志(读/写)
	__u16 len;	//消息长度
	__u8 *buf;	//缓冲区
};

     5.1  i2c读写控制数据结构体

  1. struct i2c_rdwr_ioctl_data {  
  2.     struct i2c_msg __user *msgs;    /* pointers to i2c_msgs */  
  3.     __u32 nmsgs;            /* number of i2c_msgs */  
  4. };  
struct i2c_rdwr_ioctl_data {
	struct i2c_msg __user *msgs;	/* pointers to i2c_msgs */
	__u32 nmsgs;			/* number of i2c_msgs */
};

    6. i2c算法

  1. struct i2c_algorithm {  
  2.     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num); //主机传输方式  
  3.     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags,     //smbus传输方式  
  4.         char read_write,u8 command, int size, union i2c_smbus_data *data);  
  5.     u32 (*functionality) (struct i2c_adapter *);    //功能检测  
  6. };  
struct i2c_algorithm {
	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, 	//smbus传输方式
		char read_write,u8 command, int size, union i2c_smbus_data *data);
	u32 (*functionality) (struct i2c_adapter *);	//功能检测
};


二. i2c总线,适配器,驱动,设备的初始化

     1. i2c总线类型

  1. struct bus_type i2c_bus_type = {  
  2.     .name       = "i2c",  
  3.     .match      = i2c_device_match, //i2c设备与驱动匹配  
  4.     .probe      = i2c_device_probe, //i2c设备probe方法  
  5.     .remove     = i2c_device_remove,    //移除  
  6.     .shutdown       = i2c_device_shutdown,  //关闭  
  7.     .pm     = &i2c_device_pm_ops,   //电源管理  
  8. };  
struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,	//i2c设备与驱动匹配
	.probe		= i2c_device_probe,	//i2c设备probe方法
	.remove		= i2c_device_remove,	//移除
	.shutdown		= i2c_device_shutdown,	//关闭
	.pm		= &i2c_device_pm_ops,	//电源管理
};

      1.1 i2c设备与驱动的匹配i2c_device_match

  1. static int i2c_device_match(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     struct i2c_client   *client = i2c_verify_client(dev);   //根据设备文件获取i2c_client  
  4.     struct i2c_driver   *driver;  
  5.     if (!client)  
  6.         return 0;  
  7.     if (of_driver_match_device(dev, drv))   //设备文件与设备驱动文件的匹配  
  8.         return 1;  
  9.   
  10.     driver = to_i2c_driver(drv);    //根据设备驱动文件获取i2c_driver  
  11.     if (driver->id_table)    //i2c_driver的id_table存在  
  12.         return i2c_match_id(driver->id_table, client) != NULL;   //匹配i2c_client和i2c_driver  
  13.   
  14.     return 0;  
  15. }  
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
	struct i2c_client	*client = i2c_verify_client(dev);	//根据设备文件获取i2c_client
	struct i2c_driver	*driver;
	if (!client)
		return 0;
	if (of_driver_match_device(dev, drv))	//设备文件与设备驱动文件的匹配
		return 1;

	driver = to_i2c_driver(drv);	//根据设备驱动文件获取i2c_driver
	if (driver->id_table)	//i2c_driver的id_table存在
		return i2c_match_id(driver->id_table, client) != NULL;	//匹配i2c_client和i2c_driver

	return 0;
}

     1.1.1 i2c_match_id函数

  1. static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,const struct i2c_client *client)  
  2. {  
  3.     while (id->name[0]) {    //判断i2c_driver->id_table->name数组中有与i2c_client->name相同的项没  
  4.         if (strcmp(client->name, id->name) == 0)  
  5.             return id;  
  6.         id++;  
  7.     }  
  8.     return NULL;  
  9. }  
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,const struct i2c_client *client)
{
	while (id->name[0]) {	//判断i2c_driver->id_table->name数组中有与i2c_client->name相同的项没
		if (strcmp(client->name, id->name) == 0)
			return id;
		id++;
	}
	return NULL;
}

     1.2 i2c探测函数

  1. static int i2c_device_probe(struct device *dev)  
  2. {  
  3.     struct i2c_client   *client = i2c_verify_client(dev);  
  4.     struct i2c_driver   *driver;  
  5.     int status;  
  6.   
  7.     if (!client)  
  8.         return 0;  
  9.     driver = to_i2c_driver(dev->driver);     //获得i2c_driver  
  10.     if (!driver->probe || !driver->id_table)  
  11.         return -ENODEV;  
  12.     client->driver = driver; //设置i2c_client->driver成员,i2c设备与驱动捆绑  
  13.     if (!device_can_wakeup(&client->dev))    //i2c设备支持唤醒  
  14.         device_init_wakeup(&client->dev,client->flags & I2C_CLIENT_WAKE); //则唤醒  
  15.     dev_dbg(dev, "probe\n");  
  16.     status = driver->probe(client, i2c_match_id(driver->id_table, client));   //调用i2c_driver->probe方法  
  17.     if (status) {  
  18.         client->driver = NULL;  
  19.         i2c_set_clientdata(client, NULL);  
  20.     }  
  21.     return status;  
  22. }  
static int i2c_device_probe(struct device *dev)
{
	struct i2c_client	*client = i2c_verify_client(dev);
	struct i2c_driver	*driver;
	int status;

	if (!client)
		return 0;
	driver = to_i2c_driver(dev->driver);		//获得i2c_driver
	if (!driver->probe || !driver->id_table)
		return -ENODEV;
	client->driver = driver;	//设置i2c_client->driver成员,i2c设备与驱动捆绑
	if (!device_can_wakeup(&client->dev))	//i2c设备支持唤醒
		device_init_wakeup(&client->dev,client->flags & I2C_CLIENT_WAKE);	//则唤醒
	dev_dbg(dev, "probe\n");
	status = driver->probe(client, i2c_match_id(driver->id_table, client));	//调用i2c_driver->probe方法
	if (status) {
		client->driver = NULL;
		i2c_set_clientdata(client, NULL);
	}
	return status;
}

     2. i2c总线的注册

  1. static int __init i2c_init(void)  
  2. {  
  3.     int retval;  
  4.     retval = bus_register(&i2c_bus_type);  
  5.     if (retval)  
  6.         return retval;  
  7. #ifdef CONFIG_I2C_COMPAT   
  8.     i2c_adapter_compat_class = class_compat_register("i2c-adapter");    //创建"/sys/class/i2c-adapter"  
  9.     if (!i2c_adapter_compat_class) {  
  10.         retval = -ENOMEM;  
  11.         goto bus_err;  
  12.     }  
  13. #endif   
  14.     retval = i2c_add_driver(&dummy_driver);  
  15.     if (retval)  
  16.         goto class_err;  
  17.     return 0;  
  18. class_err:  
  19. #ifdef CONFIG_I2C_COMPAT   
  20.     class_compat_unregister(i2c_adapter_compat_class);  
  21. bus_err:  
  22. #endif   
  23.     bus_unregister(&i2c_bus_type);  
  24.     return retval;  
  25. }  
static int __init i2c_init(void)
{
	int retval;
	retval = bus_register(&i2c_bus_type);
	if (retval)
		return retval;
#ifdef CONFIG_I2C_COMPAT
	i2c_adapter_compat_class = class_compat_register("i2c-adapter");	//创建"/sys/class/i2c-adapter"
	if (!i2c_adapter_compat_class) {
		retval = -ENOMEM;
		goto bus_err;
	}
#endif
	retval = i2c_add_driver(&dummy_driver);
	if (retval)
		goto class_err;
	return 0;
class_err:
#ifdef CONFIG_I2C_COMPAT
	class_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endif
	bus_unregister(&i2c_bus_type);
	return retval;
}

    3. i2c设备的初始化工作

  1. static int __init i2c_dev_init(void)  
  2. {  
  3.     int res;  
  4.     printk(KERN_INFO "i2c /dev entries driver\n");  
  5.     res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);  //注册字符设备,#define I2C_MAJOR 89  
  6.     if (res)  
  7.         goto out;  
  8.   
  9.     i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");   //创建"/sys/class/i2c-dev"  
  10.     if (IS_ERR(i2c_dev_class)) {  
  11.         res = PTR_ERR(i2c_dev_class);  
  12.         goto out_unreg_chrdev;  
  13.     }  
  14.     res = i2c_add_driver(&i2cdev_driver);   //注册i2c驱动 i2cdev_driver   
  15.     if (res)  
  16.         goto out_unreg_class;  
  17.     return 0;  
  18. out_unreg_class:  
  19.     class_destroy(i2c_dev_class);  
  20. out_unreg_chrdev:  
  21.     unregister_chrdev(I2C_MAJOR, "i2c");  
  22. out:  
  23.     printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);  
  24.     return res;  
  25. }   
static int __init i2c_dev_init(void)
{
	int res;
	printk(KERN_INFO "i2c /dev entries driver\n");
	res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);	//注册字符设备,#define I2C_MAJOR 89
	if (res)
		goto out;

	i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");	//创建"/sys/class/i2c-dev"
	if (IS_ERR(i2c_dev_class)) {
		res = PTR_ERR(i2c_dev_class);
		goto out_unreg_chrdev;
	}
	res = i2c_add_driver(&i2cdev_driver);	//注册i2c驱动 i2cdev_driver 
	if (res)
		goto out_unreg_class;
	return 0;
out_unreg_class:
	class_destroy(i2c_dev_class);
out_unreg_chrdev:
	unregister_chrdev(I2C_MAJOR, "i2c");
out:
	printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
	return res;
} 

      3.1 i2c字符设备操作函数集

  1. static const struct file_operations i2cdev_fops = {  
  2.     .owner      = THIS_MODULE,  
  3.     .llseek     = no_llseek,  
  4.     .read       = i2cdev_read,  //读   
  5.     .write      = i2cdev_write, //写  
  6.     .unlocked_ioctl = i2cdev_ioctl, //控制   
  7.     .open       = i2cdev_open,  //打开  
  8.     .release        = i2cdev_release, //释放  
  9. };  
static const struct file_operations i2cdev_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.read		= i2cdev_read,	//读
	.write		= i2cdev_write,	//写
	.unlocked_ioctl	= i2cdev_ioctl,	//控制
	.open		= i2cdev_open,	//打开
	.release		= i2cdev_release, //释放
};

     3.1.1 打开i2c字符设备

  1. static int i2cdev_open(struct inode *inode, struct file *file)  
  2. {  
  3.     unsigned int minor = iminor(inode); //根据节点获取次设备号  
  4.     struct i2c_client *client;  
  5.     struct i2c_adapter *adap;  
  6.     struct i2c_dev *i2c_dev;  
  7.   
  8.     i2c_dev = i2c_dev_get_by_minor(minor);  //根据次设备号获取i2c_dev  
  9.     if (!i2c_dev)  
  10.         return -ENODEV;  
  11.     adap = i2c_get_adapter(i2c_dev->adap->nr);    //获取i2c_adapter  
  12.     if (!adap)  
  13.         return -ENODEV;  
  14.     client = kzalloc(sizeof(*client), GFP_KERNEL);  //分配i2c_client内存  
  15.     if (!client) {  
  16.         i2c_put_adapter(adap);  
  17.         return -ENOMEM;  
  18.     }  
  19.     snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);    //修改i2c_client->name  
  20.     client->driver = &i2cdev_driver; //设置i2c_client->driver为i2cdev_driver  
  21.     client->adapter = adap;      //设置i2c_client->adapter  
  22.     file->private_data = client; //将i2c_client放在文件的私有数据段  
  23.     return 0;  
  24. }  
static int i2cdev_open(struct inode *inode, struct file *file)
{
	unsigned int minor = iminor(inode);	//根据节点获取次设备号
	struct i2c_client *client;
	struct i2c_adapter *adap;
	struct i2c_dev *i2c_dev;

	i2c_dev = i2c_dev_get_by_minor(minor);	//根据次设备号获取i2c_dev
	if (!i2c_dev)
		return -ENODEV;
	adap = i2c_get_adapter(i2c_dev->adap->nr);	//获取i2c_adapter
	if (!adap)
		return -ENODEV;
	client = kzalloc(sizeof(*client), GFP_KERNEL);	//分配i2c_client内存
	if (!client) {
		i2c_put_adapter(adap);
		return -ENOMEM;
	}
	snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);	//修改i2c_client->name
	client->driver = &i2cdev_driver;	//设置i2c_client->driver为i2cdev_driver
	client->adapter = adap;		//设置i2c_client->adapter
	file->private_data = client;	//将i2c_client放在文件的私有数据段
	return 0;
}

     3.1.2 读i2c字符设备

  1. static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,loff_t *offset)  
  2. {  
  3.     char *tmp;  
  4.     int ret;  
  5.     struct i2c_client *client = file->private_data;  //从私有数据段取出i2c_client  
  6.     if (count > 8192)  
  7.         count = 8192;  
  8.     tmp = kmalloc(count, GFP_KERNEL);   //分配临时缓冲区  
  9.     if (tmp == NULL)  
  10.         return -ENOMEM;  
  11.     pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",iminor(file->f_path.dentry->d_inode), count);  
  12.     ret = i2c_master_recv(client, tmp, count);  //调用i2c_master_recv函数(见 七 详述)  
  13.     if (ret >= 0)  
  14.         ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;    //复制数据到用户空间  
  15.     kfree(tmp);  
  16.     return ret;  
  17. }  
static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,loff_t *offset)
{
	char *tmp;
	int ret;
	struct i2c_client *client = file->private_data;	//从私有数据段取出i2c_client
	if (count > 8192)
		count = 8192;
	tmp = kmalloc(count, GFP_KERNEL);	//分配临时缓冲区
	if (tmp == NULL)
		return -ENOMEM;
	pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",iminor(file->f_path.dentry->d_inode), count);
	ret = i2c_master_recv(client, tmp, count);	//调用i2c_master_recv函数(见 七 详述)
	if (ret >= 0)
		ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;	//复制数据到用户空间
	kfree(tmp);
	return ret;
}

     3.1.3 写i2c字符设备

  1. static ssize_t i2cdev_write(struct file *file, const char __user *buf,size_t count, loff_t *offset)  
  2. {  
  3.     int ret;  
  4.     char *tmp;  
  5.     struct i2c_client *client = file->private_data;  //从私有数据段取出  
  6.     if (count > 8192)  
  7.         count = 8192;  
  8.     tmp = memdup_user(buf, count);  
  9.     if (IS_ERR(tmp))  
  10.         return PTR_ERR(tmp);  
  11.     pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",iminor(file->f_path.dentry->d_inode), count);  
  12.     ret = i2c_master_send(client, tmp, count);  //i2c发送数据 (见 七 详述)  
  13.     kfree(tmp);  
  14.     return ret;  
  15. }  
static ssize_t i2cdev_write(struct file *file, const char __user *buf,size_t count, loff_t *offset)
{
	int ret;
	char *tmp;
	struct i2c_client *client = file->private_data;	//从私有数据段取出
	if (count > 8192)
		count = 8192;
	tmp = memdup_user(buf, count);
	if (IS_ERR(tmp))
		return PTR_ERR(tmp);
	pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",iminor(file->f_path.dentry->d_inode), count);
	ret = i2c_master_send(client, tmp, count);	//i2c发送数据 (见 七 详述)
	kfree(tmp);
	return ret;
}

     3.1.4 控制i2c字符设备

  1. static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  
  2. {  
  3.     struct i2c_client *client = file->private_data;  
  4.     unsigned long funcs;  
  5.     dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",cmd, arg);  
  6.     switch (cmd) {  
  7.     case I2C_SLAVE:  
  8.     case I2C_SLAVE_FORCE:  
  9.         if ((arg > 0x3ff) ||  
  10.             (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))  
  11.             return -EINVAL;  
  12.         if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))  
  13.             return -EBUSY;  
  14.         client->addr = arg;  
  15.         return 0;  
  16.     case I2C_TENBIT:  
  17.         if (arg)  
  18.             client->flags |= I2C_M_TEN;  
  19.         else  
  20.             client->flags &= ~I2C_M_TEN;  
  21.         return 0;  
  22.     case I2C_PEC:  
  23.         if (arg)  
  24.             client->flags |= I2C_CLIENT_PEC;  
  25.         else  
  26.             client->flags &= ~I2C_CLIENT_PEC;  
  27.         return 0;  
  28.     case I2C_FUNCS:  
  29.         funcs = i2c_get_functionality(client->adapter);  
  30.         return put_user(funcs, (unsigned long __user *)arg);  
  31.     case I2C_RDWR:  
  32.         return i2cdev_ioctl_rdrw(client, arg);  //i2c读写命令 (第 七 详述)  
  33.     case I2C_SMBUS:  
  34.         return i2cdev_ioctl_smbus(client, arg); //i2c读写命令 SMBUS  
  35.     case I2C_RETRIES:  
  36.         client->adapter->retries = arg;  
  37.         break;  
  38.     case I2C_TIMEOUT:  
  39.         client->adapter->timeout = msecs_to_jiffies(arg * 10);  
  40.         break;  
  41.     default:  
  42.         return -ENOTTY;  
  43.     }  
  44.     return 0;  
  45. }  
static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct i2c_client *client = file->private_data;
	unsigned long funcs;
	dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",cmd, arg);
	switch (cmd) {
	case I2C_SLAVE:
	case I2C_SLAVE_FORCE:
		if ((arg > 0x3ff) ||
		    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
			return -EINVAL;
		if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
			return -EBUSY;
		client->addr = arg;
		return 0;
	case I2C_TENBIT:
		if (arg)
			client->flags |= I2C_M_TEN;
		else
			client->flags &= ~I2C_M_TEN;
		return 0;
	case I2C_PEC:
		if (arg)
			client->flags |= I2C_CLIENT_PEC;
		else
			client->flags &= ~I2C_CLIENT_PEC;
		return 0;
	case I2C_FUNCS:
		funcs = i2c_get_functionality(client->adapter);
		return put_user(funcs, (unsigned long __user *)arg);
	case I2C_RDWR:
		return i2cdev_ioctl_rdrw(client, arg);	//i2c读写命令 (第 七 详述)
	case I2C_SMBUS:
		return i2cdev_ioctl_smbus(client, arg);	//i2c读写命令 SMBUS
	case I2C_RETRIES:
		client->adapter->retries = arg;
		break;
	case I2C_TIMEOUT:
		client->adapter->timeout = msecs_to_jiffies(arg * 10);
		break;
	default:
		return -ENOTTY;
	}
	return 0;
}

      3.2 i2cdev_driver驱动

  1. static struct i2c_driver i2cdev_driver = {  
  2.     .driver = {  
  3.         .name   = "dev_driver",  
  4.     },  
  5.     .attach_adapter = i2cdev_attach_adapter,    //连接适配器  
  6.     .detach_adapter = i2cdev_detach_adapter,    //断开适配器  
  7. };  
static struct i2c_driver i2cdev_driver = {
	.driver = {
		.name	= "dev_driver",
	},
	.attach_adapter	= i2cdev_attach_adapter,	//连接适配器
	.detach_adapter	= i2cdev_detach_adapter,	//断开适配器
};

三. i2c适配器的添加与删除
     1. 添加适配器

  1. int i2c_add_adapter(struct i2c_adapter *adapter)  
  2. {  
  3.     int id, res = 0;  
  4. retry:  
  5.     if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) //根据idr机制获取适配器编号  
  6.         return -ENOMEM;  
  7.     mutex_lock(&core_lock);  
  8.     res = idr_get_new_above(&i2c_adapter_idr, adapter,__i2c_first_dynamic_bus_num, &id);  
  9.     mutex_unlock(&core_lock);  
  10.     if (res < 0) {  
  11.         if (res == -EAGAIN)  
  12.             goto retry;  
  13.         return res;  
  14.     }  
  15.     adapter->nr = id;    //设置i2c_adapter->nr  
  16.     return i2c_register_adapter(adapter);   //注册i2c_adapter  
  17. }  
int i2c_add_adapter(struct i2c_adapter *adapter)
{
	int	id, res = 0;
retry:
	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)	//根据idr机制获取适配器编号
		return -ENOMEM;
	mutex_lock(&core_lock);
	res = idr_get_new_above(&i2c_adapter_idr, adapter,__i2c_first_dynamic_bus_num, &id);
	mutex_unlock(&core_lock);
	if (res < 0) {
		if (res == -EAGAIN)
			goto retry;
		return res;
	}
	adapter->nr = id;	//设置i2c_adapter->nr
	return i2c_register_adapter(adapter);	//注册i2c_adapter
}

     1.1 i2c_register_adapter

  1. static int i2c_register_adapter(struct i2c_adapter *adap)  
  2. {  
  3.     int res = 0;  
  4.     if (unlikely(WARN_ON(!i2c_bus_type.p))) {  
  5.         res = -EAGAIN;  
  6.         goto out_list;  
  7.     }  
  8.     if (unlikely(adap->name[0] == '\0')) {  
  9.         pr_err("i2c-core: Attempt to register an adapter with no name!\n");  
  10.         return -EINVAL;  
  11.     }  
  12.     if (unlikely(!adap->algo)) {  
  13.         pr_err("i2c-core: Attempt to register adapter '%s' with no algo!\n", adap->name);  
  14.         return -EINVAL;  
  15.     }  
  16.     rt_mutex_init(&adap->bus_lock);  
  17.     mutex_init(&adap->userspace_clients_lock);  
  18.     INIT_LIST_HEAD(&adap->userspace_clients);    //初始化支持i2c_client链表头  
  19.     if (adap->timeout == 0)  
  20.         adap->timeout = HZ;  //设置超时值   
  21.     dev_set_name(&adap->dev, "i2c-%d", adap->nr); //设置i2c_adapter->dev->name  
  22.     adap->dev.bus = &i2c_bus_type;   //设置i2c_adapter->dev.bus为i2c_bus_type  
  23.     adap->dev.type = &i2c_adapter_type;  //设置i2c_adapter->dev.type  
  24.     res = device_register(&adap->dev);   //注册i2c_adapter的设备文件  
  25.     if (res)  
  26.         goto out_list;  
  27.     dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);  
  28. #ifdef CONFIG_I2C_COMPAT   
  29.     res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,adap->dev.parent);    //创建"/sys/class/i2c-adapter/i2c-XX"链接文件  
  30.     if (res)  
  31.         dev_warn(&adap->dev,"Failed to create compatibility class link\n");  
  32. #endif   
  33.     if (adap->nr < __i2c_first_dynamic_bus_num)   //__i2c_first_dynamic_bus_num数值在i2c_register_board_info中设置  
  34.         i2c_scan_static_board_info(adap);   //扫描用板级声明的i2c设备并添加,后面细化  
  35.     mutex_lock(&core_lock); //遍历i2c_bus_type总线类型的设备文件,调用__process_new_adapter   
  36.     bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);//最终会调用i2c_driver->attach_adapter  
  37.     mutex_unlock(&core_lock);  
  38.     return 0;  
  39. out_list:  
  40.     mutex_lock(&core_lock);  
  41.     idr_remove(&i2c_adapter_idr, adap->nr);  
  42.     mutex_unlock(&core_lock);  
  43.     return res;  
  44. }  
static int i2c_register_adapter(struct i2c_adapter *adap)
{
	int res = 0;
	if (unlikely(WARN_ON(!i2c_bus_type.p))) {
		res = -EAGAIN;
		goto out_list;
	}
	if (unlikely(adap->name[0] == '\0')) {
		pr_err("i2c-core: Attempt to register an adapter with no name!\n");
		return -EINVAL;
	}
	if (unlikely(!adap->algo)) {
		pr_err("i2c-core: Attempt to register adapter '%s' with no algo!\n", adap->name);
		return -EINVAL;
	}
	rt_mutex_init(&adap->bus_lock);
	mutex_init(&adap->userspace_clients_lock);
	INIT_LIST_HEAD(&adap->userspace_clients);	//初始化支持i2c_client链表头
	if (adap->timeout == 0)
		adap->timeout = HZ;	//设置超时值
	dev_set_name(&adap->dev, "i2c-%d", adap->nr);	//设置i2c_adapter->dev->name
	adap->dev.bus = &i2c_bus_type;	//设置i2c_adapter->dev.bus为i2c_bus_type
	adap->dev.type = &i2c_adapter_type;	//设置i2c_adapter->dev.type
	res = device_register(&adap->dev);	//注册i2c_adapter的设备文件
	if (res)
		goto out_list;
	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
#ifdef CONFIG_I2C_COMPAT
	res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,adap->dev.parent);	//创建"/sys/class/i2c-adapter/i2c-XX"链接文件
	if (res)
		dev_warn(&adap->dev,"Failed to create compatibility class link\n");
#endif
	if (adap->nr < __i2c_first_dynamic_bus_num)	//__i2c_first_dynamic_bus_num数值在i2c_register_board_info中设置
		i2c_scan_static_board_info(adap);	//扫描用板级声明的i2c设备并添加,后面细化
	mutex_lock(&core_lock);	//遍历i2c_bus_type总线类型的设备文件,调用__process_new_adapter 
	bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);//最终会调用i2c_driver->attach_adapter
	mutex_unlock(&core_lock);
	return 0;
out_list:
	mutex_lock(&core_lock);
	idr_remove(&i2c_adapter_idr, adap->nr);
	mutex_unlock(&core_lock);
	return res;
}

这里还有一个函数可以添加适配器i2c_add_numbered_adapter原理一样.

     2. 删除适配器

  1. int i2c_del_adapter(struct i2c_adapter *adap)  
  2. {  
  3.     int res = 0;  
  4.     struct i2c_adapter *found;  
  5.     struct i2c_client *client, *next;  
  6.     mutex_lock(&core_lock);  
  7.     found = idr_find(&i2c_adapter_idr, adap->nr);  
  8.     mutex_unlock(&core_lock);  
  9.     if (found != adap) {  
  10.         pr_debug("i2c-core: attempting to delete unregistered adapter [%s]\n", adap->name);  
  11.         return -EINVAL;  
  12.     }  
  13.     mutex_lock(&core_lock); //遍历i2c_bus_type 总线类型的设备文件,调用__process_removed_adapter  
  14.     res = bus_for_each_drv(&i2c_bus_type, NULL, adap,__process_removed_adapter);    //最终调用i2c_driver->detach_adapter  
  15.     mutex_unlock(&core_lock);  
  16.     if (res)  
  17.         return res;  
  18.     mutex_lock(&adap->userspace_clients_lock);  
  19.     list_for_each_entry_safe(client, next, &adap->userspace_clients,detected) {  //遍历所有挂载适配器上的i2c设备  
  20.         dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,client->addr);  
  21.         list_del(&client->detected); //移出"检测到"链表  
  22.         i2c_unregister_device(client);  //注销i2c_client  
  23.     }  
  24.     mutex_unlock(&adap->userspace_clients_lock);  
  25.     res = device_for_each_child(&adap->dev, NULL, __unregister_client);  
  26. #ifdef CONFIG_I2C_COMPAT   
  27.     class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,adap->dev.parent);  //删除"/sys/class/i2c-adapter/"的链接  
  28. #endif   
  29.     dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);  
  30.     init_completion(&adap->dev_released);  
  31.     device_unregister(&adap->dev);   //注销设备文件  
  32.     wait_for_completion(&adap->dev_released);  
  33.     mutex_lock(&core_lock);  
  34.     idr_remove(&i2c_adapter_idr, adap->nr);  //移除idr数值  
  35.     mutex_unlock(&core_lock);  
  36.     memset(&adap->dev, 0, sizeof(adap->dev));  
  37.     return 0;  
  38. }  
int i2c_del_adapter(struct i2c_adapter *adap)
{
	int res = 0;
	struct i2c_adapter *found;
	struct i2c_client *client, *next;
	mutex_lock(&core_lock);
	found = idr_find(&i2c_adapter_idr, adap->nr);
	mutex_unlock(&core_lock);
	if (found != adap) {
		pr_debug("i2c-core: attempting to delete unregistered adapter [%s]\n", adap->name);
		return -EINVAL;
	}
	mutex_lock(&core_lock);	//遍历i2c_bus_type 总线类型的设备文件,调用__process_removed_adapter
	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,__process_removed_adapter);	//最终调用i2c_driver->detach_adapter
	mutex_unlock(&core_lock);
	if (res)
		return res;
	mutex_lock(&adap->userspace_clients_lock);
	list_for_each_entry_safe(client, next, &adap->userspace_clients,detected) {	//遍历所有挂载适配器上的i2c设备
		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,client->addr);
		list_del(&client->detected);	//移出"检测到"链表
		i2c_unregister_device(client);	//注销i2c_client
	}
	mutex_unlock(&adap->userspace_clients_lock);
	res = device_for_each_child(&adap->dev, NULL, __unregister_client);
#ifdef CONFIG_I2C_COMPAT
	class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,adap->dev.parent);	//删除"/sys/class/i2c-adapter/"的链接
#endif
	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
	init_completion(&adap->dev_released);
	device_unregister(&adap->dev);	//注销设备文件
	wait_for_completion(&adap->dev_released);
	mutex_lock(&core_lock);
	idr_remove(&i2c_adapter_idr, adap->nr);	//移除idr数值
	mutex_unlock(&core_lock);
	memset(&adap->dev, 0, sizeof(adap->dev));
	return 0;
}

四. 添加删除i2c_driver

     1. 添加i2c_driver

  1. static inline int i2c_add_driver(struct i2c_driver *driver)  
  2. {  
  3.     return i2c_register_driver(THIS_MODULE, driver);    //注册i2c_driver  
  4. }  
static inline int i2c_add_driver(struct i2c_driver *driver)
{
	return i2c_register_driver(THIS_MODULE, driver);	//注册i2c_driver
}

     1.1 i2c_register_driver

  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)  
  2. {  
  3.     int res;  
  4.     if (unlikely(WARN_ON(!i2c_bus_type.p)))  
  5.         return -EAGAIN;  
  6.     driver->driver.owner = owner;    //设置驱动模块所有者  
  7.     driver->driver.bus = &i2c_bus_type;  //设置设备驱动文件的总线类型为i2c_bus_type  
  8.     res = driver_register(&driver->driver);  //注册设备驱动文件  
  9.     if (res)  
  10.         return res;  
  11.     pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);  
  12.     INIT_LIST_HEAD(&driver->clients);    //初始化i2c_driver支持i2c_client链表头  
  13.     mutex_lock(&core_lock); //遍历i2c_bus_type总线类型的设备文件,调用__process_new_driver函数  
  14.     bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);    //最终调用i2c_driver->attach_adapter  
  15.     mutex_unlock(&core_lock);  
  16.     return 0;  
  17. }  
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
	int res;
	if (unlikely(WARN_ON(!i2c_bus_type.p)))
		return -EAGAIN;
	driver->driver.owner = owner;	//设置驱动模块所有者
	driver->driver.bus = &i2c_bus_type;	//设置设备驱动文件的总线类型为i2c_bus_type
	res = driver_register(&driver->driver);	//注册设备驱动文件
	if (res)
		return res;
	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
	INIT_LIST_HEAD(&driver->clients);	//初始化i2c_driver支持i2c_client链表头
	mutex_lock(&core_lock);	//遍历i2c_bus_type总线类型的设备文件,调用__process_new_driver函数
	bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);	//最终调用i2c_driver->attach_adapter
	mutex_unlock(&core_lock);
	return 0;
}

      2. 删除i2c_driver

  1. void i2c_del_driver(struct i2c_driver *driver)  
  2. {  
  3.     mutex_lock(&core_lock); //遍历i2c_bus_type总线类型的设备文件,调用__process_removed_driver函数  
  4.     bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);    //最终调用i2c_driver->detach_adapter   
  5.     mutex_unlock(&core_lock);  
  6.     driver_unregister(&driver->driver);  //注销设备驱动文件  
  7.     pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);  
  8. }  
void i2c_del_driver(struct i2c_driver *driver)
{
	mutex_lock(&core_lock);	//遍历i2c_bus_type总线类型的设备文件,调用__process_removed_driver函数
	bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);	//最终调用i2c_driver->detach_adapter 
	mutex_unlock(&core_lock);
	driver_unregister(&driver->driver);	//注销设备驱动文件
	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
}

五. 注册i2c板级信息

     1. 注册板级i2c驱动

  1. int __init i2c_register_board_info(int busnum,struct i2c_board_info const *info, unsigned len)  
  2. {  
  3.     int status;  
  4.     down_write(&__i2c_board_lock);  
  5.     /* dynamic bus numbers will be assigned after the last static one */  
  6.     if (busnum >= __i2c_first_dynamic_bus_num)  
  7.         __i2c_first_dynamic_bus_num = busnum + 1;   //设置全局变量__i2c_first_dynamic_bus_num  
  8.     for (status = 0; len; len--, info++) {  
  9.         struct i2c_devinfo  *devinfo;  
  10.         devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);  
  11.         if (!devinfo) {  
  12.             pr_debug("i2c-core: can't register boardinfo!\n");  
  13.             status = -ENOMEM;  
  14.             break;  
  15.         }  
  16.         devinfo->busnum = busnum;    //设置devinfo  
  17.         devinfo->board_info = *info; //设置devinfo的板级别信息  
  18.         list_add_tail(&devinfo->list, &__i2c_board_list);    //添加到全局__i2c_board_list链表中  
  19.     }  
  20.     up_write(&__i2c_board_lock);  
  21.     return status;  
  22. }  
int __init i2c_register_board_info(int busnum,struct i2c_board_info const *info, unsigned len)
{
	int status;
	down_write(&__i2c_board_lock);
	/* dynamic bus numbers will be assigned after the last static one */
	if (busnum >= __i2c_first_dynamic_bus_num)
		__i2c_first_dynamic_bus_num = busnum + 1;	//设置全局变量__i2c_first_dynamic_bus_num
	for (status = 0; len; len--, info++) {
		struct i2c_devinfo	*devinfo;
		devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
		if (!devinfo) {
			pr_debug("i2c-core: can't register boardinfo!\n");
			status = -ENOMEM;
			break;
		}
		devinfo->busnum = busnum;	//设置devinfo
		devinfo->board_info = *info;	//设置devinfo的板级别信息
		list_add_tail(&devinfo->list, &__i2c_board_list);	//添加到全局__i2c_board_list链表中
	}
	up_write(&__i2c_board_lock);
	return status;
}

 这里有多少个i2c总线,就必须调用多少次i2c_register_board_info带入的busnum依次递增(i2c_register_board_info(1,...);i2c_register_board_info(2,...)....)
全局变量__i2c_first_dynamic_bus_num值i2c_add_adapter函数中调用到. 

     2. 回顾下前面i2c_add_adapter函数中提到的i2c_scan_static_board_info函数

  1. static void i2c_scan_static_board_info(struct i2c_adapter *adapter)  
  2. {  
  3.     struct i2c_devinfo  *devinfo;  
  4.     down_read(&__i2c_board_lock);  
  5.     list_for_each_entry(devinfo, &__i2c_board_list, list) { //遍历全局__i2c_board_list链表  
  6.         if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter,&devinfo->board_info))     
  7.         //匹配的i2c适配器下,添加devinfo的板级信息指定的i2c_device  
  8.             dev_err(&adapter->dev,"Can't create device at 0x%02x\n",devinfo->board_info.addr);  
  9.     }  
  10.     up_read(&__i2c_board_lock);  
  11. }  
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
	struct i2c_devinfo	*devinfo;
	down_read(&__i2c_board_lock);
	list_for_each_entry(devinfo, &__i2c_board_list, list) {	//遍历全局__i2c_board_list链表
		if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter,&devinfo->board_info))	
		//匹配的i2c适配器下,添加devinfo的板级信息指定的i2c_device
			dev_err(&adapter->dev,"Can't create device at 0x%02x\n",devinfo->board_info.addr);
	}
	up_read(&__i2c_board_lock);
}

     3. 板级声明的i2c_client的注册

  1. struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  
  2. {  
  3.     struct i2c_client   *client;  
  4.     int status;  
  5.     client = kzalloc(sizeof *client, GFP_KERNEL);   //分配i2c_client内存  
  6.     if (!client)  
  7.         return NULL;  
  8.     client->adapter = adap;  //指定i2c_client的适配器  
  9.     client->dev.platform_data = info->platform_data;  //设置i2c_client设备文件的平台数据  
  10.     if (info->archdata)  
  11.         client->dev.archdata = *info->archdata;  
  12.     client->flags = info->flags;  //设置i2c_client->flags  
  13.     client->addr = info->addr;        //设置i2c_client地址  
  14.     client->irq = info->irq;  //设置i2c_client中断号  
  15.     strlcpy(client->name, info->type, sizeof(client->name));   //设置i2c_client->name  
  16.     status = i2c_check_client_addr_validity(client);    //检测i2c_client地址合法性(0x01~0x7f)  
  17.     if (status) {  
  18.         dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);  
  19.         goto out_err_silent;  
  20.     }  
  21.     status = i2c_check_addr_busy(adap, client->addr);    //检测地址是否给占用  
  22.     if (status)  
  23.         goto out_err;  
  24.     client->dev.parent = &client->adapter->dev;    //设置i2c_client的父设备  
  25.     client->dev.bus = &i2c_bus_type;     //设置i2c_client的总线类型  
  26.     client->dev.type = &i2c_client_type;     //设置i2c_client的设备类型  
  27. #ifdef CONFIG_OF   
  28.     client->dev.of_node = info->of_node;  
  29. #endif   
  30.     dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),client->addr); //设置i2c_client设备文件的设备名  
  31.     status = device_register(&client->dev);  //注册设备文件  
  32.     if (status)  
  33.         goto out_err;  
  34.     dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",client->name, dev_name(&client->dev));  
  35.     return client;  
  36. out_err:  
  37.     dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x(%d)\n", client->name, client->addr, status);  
  38. out_err_silent:  
  39.     kfree(client);  
  40.     return NULL;  
  41. }  
struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
	struct i2c_client	*client;
	int status;
	client = kzalloc(sizeof *client, GFP_KERNEL);	//分配i2c_client内存
	if (!client)
		return NULL;
	client->adapter = adap;	//指定i2c_client的适配器
	client->dev.platform_data = info->platform_data;	//设置i2c_client设备文件的平台数据
	if (info->archdata)
		client->dev.archdata = *info->archdata;
	client->flags = info->flags;	//设置i2c_client->flags
	client->addr = info->addr;		//设置i2c_client地址
	client->irq = info->irq;	//设置i2c_client中断号
	strlcpy(client->name, info->type, sizeof(client->name));	//设置i2c_client->name
	status = i2c_check_client_addr_validity(client);	//检测i2c_client地址合法性(0x01~0x7f)
	if (status) {
		dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
		goto out_err_silent;
	}
	status = i2c_check_addr_busy(adap, client->addr);	//检测地址是否给占用
	if (status)
		goto out_err;
	client->dev.parent = &client->adapter->dev;	//设置i2c_client的父设备
	client->dev.bus = &i2c_bus_type;		//设置i2c_client的总线类型
	client->dev.type = &i2c_client_type;		//设置i2c_client的设备类型
#ifdef CONFIG_OF
	client->dev.of_node = info->of_node;
#endif
	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),client->addr);	//设置i2c_client设备文件的设备名
	status = device_register(&client->dev);	//注册设备文件
	if (status)
		goto out_err;
	dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",client->name, dev_name(&client->dev));
	return client;
out_err:
	dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x(%d)\n", client->name, client->addr, status);
out_err_silent:
	kfree(client);
	return NULL;
}

 

六. attach和detach

1. 前面i2c_adapter和i2c_driver驱动添加和删除都会遍历i2c_bus_type总线类型的设备,然后调用各自的函数,__process_new_adapter,__process_removed_adapter,__process_new_driver,__process_removed_driver

  1. __process_new_adapter -->i2c_do_add_adapter -->attach_adapter   
  2. __process_new_driver -->i2c_do_add_adapter -->attach_adapter  
  3.   
  4. __process_removed_adapter -->i2c_do_del_adapter -->detach_adapter  
  5. __process_removed_driver -->i2c_do_del_adapter -->detach_adapter  
__process_new_adapter -->i2c_do_add_adapter -->attach_adapter 
__process_new_driver -->i2c_do_add_adapter -->attach_adapter

__process_removed_adapter -->i2c_do_del_adapter -->detach_adapter
__process_removed_driver -->i2c_do_del_adapter -->detach_adapter


七. i2c主机读写

     1.  发送i2c_master_send

  1. int i2c_master_send(struct i2c_client *client, const char *buf, int count)  
  2. {  
  3.     int ret;  
  4.     struct i2c_adapter *adap = client->adapter;  //获得i2c_adapter  
  5.     struct i2c_msg msg;  
  6.     msg.addr = client->addr; //设置i2c_msg的地址  
  7.     msg.flags = client->flags & I2C_M_TEN;   //设置标志  
  8.     msg.len = count;    //设置i2c_msg长度   
  9.     msg.buf = (char *)buf;  //设置i2c_msg缓冲区  
  10.     ret = i2c_transfer(adap, &msg, 1);  //调用i2c_transfer函数  
  11.     return (ret == 1) ? count : ret;  
  12. }  
int i2c_master_send(struct i2c_client *client, const char *buf, int count)
{
	int ret;
	struct i2c_adapter *adap = client->adapter;	//获得i2c_adapter
	struct i2c_msg msg;
	msg.addr = client->addr;	//设置i2c_msg的地址
	msg.flags = client->flags & I2C_M_TEN;	//设置标志
	msg.len = count;	//设置i2c_msg长度
	msg.buf = (char *)buf;	//设置i2c_msg缓冲区
	ret = i2c_transfer(adap, &msg, 1);	//调用i2c_transfer函数
	return (ret == 1) ? count : ret;
}

     2. 接收i2c_master_recv

  1. int i2c_master_recv(struct i2c_client *client, char *buf, int count)  
  2. {  
  3.     struct i2c_adapter *adap = client->adapter;  //获得i2c_adapter  
  4.     struct i2c_msg msg;   
  5.     int ret;  
  6.     msg.addr = client->addr; //设置i2c_msg地址  
  7.     msg.flags = client->flags & I2C_M_TEN;   //设置标志  
  8.     msg.flags |= I2C_M_RD;  //设置标志为读   
  9.     msg.len = count;    //设置i2c_msg长度  
  10.     msg.buf = buf;  //设置i2c_msg缓冲区   
  11.     ret = i2c_transfer(adap, &msg, 1);  //调用i2c_transfer函数  
  12.     return (ret == 1) ? count : ret;  
  13. }  
int i2c_master_recv(struct i2c_client *client, char *buf, int count)
{
	struct i2c_adapter *adap = client->adapter;	//获得i2c_adapter
	struct i2c_msg msg;	
	int ret;
	msg.addr = client->addr;	//设置i2c_msg地址
	msg.flags = client->flags & I2C_M_TEN;	//设置标志
	msg.flags |= I2C_M_RD;	//设置标志为读
	msg.len = count;	//设置i2c_msg长度
	msg.buf = buf;	//设置i2c_msg缓冲区
	ret = i2c_transfer(adap, &msg, 1);	//调用i2c_transfer函数
	return (ret == 1) ? count : ret;
}

     3. 控制

  1. static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,unsigned long arg)  
  2. {  
  3.     struct i2c_rdwr_ioctl_data rdwr_arg;  
  4.     struct i2c_msg *rdwr_pa;  
  5.     u8 __user **data_ptrs;  
  6.     int i, res;  
  7.   
  8.     if (copy_from_user(&rdwr_arg,(struct i2c_rdwr_ioctl_data __user *)arg,sizeof(rdwr_arg)))    //用户空间复制信息数据  
  9.         return -EFAULT;  
  10.     if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)        //最大支持同时发生1024个消息  
  11.         return -EINVAL;  
  12.     rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL); //分配i2c_msg数据内存  
  13.     if (!rdwr_pa)  
  14.         return -ENOMEM;  
  15.     if (copy_from_user(rdwr_pa, rdwr_arg.msgs,rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {   //用户空间复制i2c_msg数据  
  16.         kfree(rdwr_pa);  
  17.         return -EFAULT;  
  18.     }  
  19.     data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);  //分配临时数据内存  
  20.     if (data_ptrs == NULL) {  
  21.         kfree(rdwr_pa);  
  22.         return -ENOMEM;  
  23.     }  
  24.     res = 0;  
  25.     for (i = 0; i < rdwr_arg.nmsgs; i++) {  
  26.         if ((rdwr_pa[i].len > 8192) ||(rdwr_pa[i].flags & I2C_M_RECV_LEN)) { //判断i2c_msg数据长度和标志的合法性  
  27.             res = -EINVAL;  
  28.             break;  
  29.         }  
  30.         data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;  
  31.         rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); //复制i2c_msg数据到rdwr_pa  
  32.         if (IS_ERR(rdwr_pa[i].buf)) {  
  33.             res = PTR_ERR(rdwr_pa[i].buf);  
  34.             break;  
  35.         }  
  36.     }  
  37.     if (res < 0) {  
  38.         int j;  
  39.         for (j = 0; j < i; ++j)  
  40.             kfree(rdwr_pa[j].buf);  
  41.         kfree(data_ptrs);  
  42.         kfree(rdwr_pa);  
  43.         return res;  
  44.     }  
  45.     res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);    //调用i2c_transfer函数传输i2c_msg  
  46.     while (i-- > 0) {  
  47.         if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {  
  48.             if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,rdwr_pa[i].len))  //将数据复制到用户空间  
  49.                 res = -EFAULT;  
  50.         }  
  51.         kfree(rdwr_pa[i].buf);  
  52.     }  
  53.     kfree(data_ptrs);  
  54.     kfree(rdwr_pa);  
  55.     return res;  
  56. }  
static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,unsigned long arg)
{
	struct i2c_rdwr_ioctl_data rdwr_arg;
	struct i2c_msg *rdwr_pa;
	u8 __user **data_ptrs;
	int i, res;

	if (copy_from_user(&rdwr_arg,(struct i2c_rdwr_ioctl_data __user *)arg,sizeof(rdwr_arg)))	//用户空间复制信息数据
		return -EFAULT;
	if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)		//最大支持同时发生1024个消息
		return -EINVAL;
	rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);	//分配i2c_msg数据内存
	if (!rdwr_pa)
		return -ENOMEM;
	if (copy_from_user(rdwr_pa, rdwr_arg.msgs,rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {	//用户空间复制i2c_msg数据
		kfree(rdwr_pa);
		return -EFAULT;
	}
	data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);	//分配临时数据内存
	if (data_ptrs == NULL) {
		kfree(rdwr_pa);
		return -ENOMEM;
	}
	res = 0;
	for (i = 0; i < rdwr_arg.nmsgs; i++) {
		if ((rdwr_pa[i].len > 8192) ||(rdwr_pa[i].flags & I2C_M_RECV_LEN)) {	//判断i2c_msg数据长度和标志的合法性
			res = -EINVAL;
			break;
		}
		data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
		rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);	//复制i2c_msg数据到rdwr_pa
		if (IS_ERR(rdwr_pa[i].buf)) {
			res = PTR_ERR(rdwr_pa[i].buf);
			break;
		}
	}
	if (res < 0) {
		int j;
		for (j = 0; j < i; ++j)
			kfree(rdwr_pa[j].buf);
		kfree(data_ptrs);
		kfree(rdwr_pa);
		return res;
	}
	res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);	//调用i2c_transfer函数传输i2c_msg
	while (i-- > 0) {
		if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
			if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,rdwr_pa[i].len))	//将数据复制到用户空间
				res = -EFAULT;
		}
		kfree(rdwr_pa[i].buf);
	}
	kfree(data_ptrs);
	kfree(rdwr_pa);
	return res;
}

     4. i2c_transfer函数

  1. int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  
  2. {  
  3.     unsigned long orig_jiffies;  
  4.     int ret, try;  
  5.     if (adap->algo->master_xfer) {    //若适配器的算法结构体中定义了master_xfer方法  
  6.         if (in_atomic() || irqs_disabled()) {  
  7.             ret = i2c_trylock_adapter(adap);  
  8.             if (!ret)  
  9.                 return -EAGAIN;  
  10.         } else {  
  11.             i2c_lock_adapter(adap);  
  12.         }  
  13.         orig_jiffies = jiffies;  
  14.         for (ret = 0, try = 0; try <= adap->retries; try++) { //重试次数  
  15.             ret = adap->algo->master_xfer(adap, msgs, num);   //则调用其master_xfer方法  
  16.             if (ret != -EAGAIN)  
  17.                 break;  
  18.             if (time_after(jiffies, orig_jiffies + adap->timeout))   //开启超时定时器  
  19.                 break;  
  20.         }  
  21.         i2c_unlock_adapter(adap);  
  22.   
  23.         return ret;  
  24.     } else {  
  25.         dev_dbg(&adap->dev, "I2C level transfers not supported\n");  
  26.         return -EOPNOTSUPP;  
  27.     }  
  28. }  
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
	unsigned long orig_jiffies;
	int ret, try;
	if (adap->algo->master_xfer) {	//若适配器的算法结构体中定义了master_xfer方法
		if (in_atomic() || irqs_disabled()) {
			ret = i2c_trylock_adapter(adap);
			if (!ret)
				return -EAGAIN;
		} else {
			i2c_lock_adapter(adap);
		}
		orig_jiffies = jiffies;
		for (ret = 0, try = 0; try <= adap->retries; try++) {	//重试次数
			ret = adap->algo->master_xfer(adap, msgs, num);	//则调用其master_xfer方法
			if (ret != -EAGAIN)
				break;
			if (time_after(jiffies, orig_jiffies + adap->timeout))	//开启超时定时器
				break;
		}
		i2c_unlock_adapter(adap);

		return ret;
	} else {
		dev_dbg(&adap->dev, "I2C level transfers not supported\n");
		return -EOPNOTSUPP;
	}
}

 

八. i2c驱动编写

     1. 针对i2c适配器

定义i2c_adapter和对应的i2c_algorithm结构体,配置参数,然后调用i2c_add_adapter添加适配器

     2.针对i2c设备

驱动端:定义i2c_driver结构体,配置id_table等参数,调用i2c_add_driver

设备端:声明板级信息I2C_BOARD_INFO,并调用i2c_register_board_info注册,或者直接使用i2c_new_device函数

上面这种写法是做在内核层,一般的目的只是为了设备和驱动匹配而调用驱动的probe方法来做i2c设备的初始化工作

又或者是像ds1307-RTC等需要给系统提供接口,频繁操作的情况.

如果设备压根就不需要初始化,那么其实做在应用层,直接用操作/dev/i2c-X,操作适配器完成读写工作便可.


九. 应用层

     1.工具i2cdetect

  1. Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]  
  2.        i2cdetect -F I2CBUS  
  3.        i2cdetect -l //检测i2c适配器  
  4.   I2CBUS is an integer or an I2C bus name  
  5.   If provided, FIRST and LAST limit the probing range.  
Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]
       i2cdetect -F I2CBUS
       i2cdetect -l	//检测i2c适配器
  I2CBUS is an integer or an I2C bus name
  If provided, FIRST and LAST limit the probing range.

    2. i2c读写工具(不支持smbus)

  1. #include <sys/types.h>   
  2. #include <fcntl.h>   
  3. #include <string.h>   
  4. #include <stdlib.h>   
  5. #include <stdio.h>   
  6. #include <linux/i2c.h>   
  7. #include <linux/i2c-dev.h>  
  8. //r devaddr reg value   
  9. //w devaddr reg value   
  10. int main(int argc ,char **argv){  
  11.     int fd=0;  
  12.     int status=0;  
  13.     struct i2c_rdwr_ioctl_data data;  
  14.     struct i2c_msg *msgs=NULL;  
  15.     unsigned int addr;  
  16.     unsigned char reg;  
  17.     unsigned char val;  
  18.     unsigned char buf[2];  
  19.     if(argc!=5)  
  20.     {  
  21.         printf("***********************************************\n");  
  22.         printf("*****        i2c read/write tool         ******\n");  
  23.         printf("*****read : r devaddr regaddr num        ******\n");  
  24.         printf("*****write: w devaddr regaddr val        ******\n");  
  25.         printf("*****             copyright by mahongbin ******\n");  
  26.         printf("***********************************************\n");  
  27.         printf("*****what the fuck of you !error command!******\n");  
  28.         return -1;  
  29.     }     
  30.     msgs=(struct i2c_msg *) malloc(sizeof(struct i2c_msg)*2);  
  31.     if(msgs==NULL){  
  32.         printf("malloc msgs error!\n");  
  33.         return -1;    
  34.     }  
  35.       
  36.     fd=open("/dev/i2c-2",O_RDWR);  
  37.     if(fd<0){  
  38.         printf("can not open i2c device!\n");  
  39.         return -1;  
  40.     }  
  41.   
  42.     addr=strtoul(argv[2],NULL,0);  
  43.     buf[0]=strtoul(argv[3],NULL,0);  
  44.     buf[1]=strtoul(argv[4],NULL,0);  
  45.   
  46. //write devaddr    
  47.   
  48.     //read register value   
  49.     if(strcmp(argv[1],"r")==0){  
  50.   
  51.         msgs[0].addr=addr;  
  52.         msgs[0].flags=0;  
  53.         msgs[0].len=1;  
  54.         msgs[0].buf=&buf[0];  
  55.       
  56.         msgs[1].addr=addr;  
  57.         msgs[1].flags=1;  
  58.         msgs[1].len=1;  
  59.         msgs[1].buf=&buf[1];  
  60.           
  61.         data.msgs=msgs;  
  62.         data.nmsgs=2;  
  63.         status=ioctl(fd,I2C_RDWR,&data);  
  64.         if(status<0){  
  65.             printf("i2c read  error!\n");         
  66.         }  
  67.         printf("[0x%02x]-(0x%02x)=0x%02x\n",addr,buf[0],buf[1]);  
  68.     }  
  69.     //write register    
  70.     else if(strcmp(argv[1],"w")==0){  
  71.           
  72.         msgs[0].addr=addr;  
  73.         msgs[0].flags=0;  
  74.         msgs[0].len=2;  
  75.         msgs[0].buf=&buf[0];  
  76.   
  77.         //msgs[1].addr=addr;   
  78.         //msgs[1].flags=0;   
  79.         //msgs[1].len=1;   
  80.         //msgs[1].buf=&buf[0];   
  81.   
  82.         data.msgs=msgs;  
  83.         data.nmsgs=1;  
  84.         status=ioctl(fd,I2C_RDWR,&data);  
  85.         if(status<0){  
  86.             printf("i2c write error2!\n");        
  87.         }  
  88.         printf("[0x%02x]-(0x%02x)=0x%02x\n",addr,buf[0],buf[1]);  
  89.     }  
  90.     else{  
  91.         printf("***********************************************\n");  
  92.         printf("*****        i2c read/write tool         ******\n");  
  93.         printf("*****read : r devaddr regaddr            ******\n");  
  94.         printf("*****write: w devaddr regaddr val        ******\n");  
  95.         printf("*****             copyright by mahongbin ******\n");  
  96.         printf("***********************************************\n");  
  97.     }  
  98.   
  99.     free(msgs);  
  100.     close(fd);  
  101.     return 0;  
  102. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值