linux i2c设备驱动

一. i2c的结构体

     1. i2c适配器

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设备

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驱动

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板级信息

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板级信息辅助宏(一般声明在板级初始化函数中)

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

     5. i2c消息

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

     5.1  i2c读写控制数据结构体

struct i2c_rdwr_ioctl_data {
	struct i2c_msg __user *msgs;	/* pointers to i2c_msgs */
	__u32 nmsgs;			/* number of i2c_msgs */
};

    6. i2c算法

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总线类型

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

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函数

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探测函数

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总线的注册

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 clas
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux I2C设备驱动Linux内核中的一个子系统,用于处理I2C总线上的设备驱动程序。I2C是一种串行通信协议,通常用于连接各种外设,例如传感器、LCD屏幕、EEPROM、温度传感器等。 Linux I2C设备驱动程序通常包括以下几个部分: 1. i2c_driver结构体:定义I2C设备驱动的属性和操作函数。这个结构体包含了设备的名称、ID等信息,以及设备的初始化函数、读写函数等。通过注册这个结构体,将I2C设备驱动程序和I2C总线绑定在一起。 2. i2c_client结构体:定义I2C设备的属性和操作函数。这个结构体包含了设备的地址、名称等信息,以及设备的读写函数等。通过这个结构体,可以访问I2C设备,读写寄存器等。 3. probe函数:用于初始化I2C设备。当I2C总线扫描到一个新的设备时,会调用该函数,完成设备的初始化工作。 4. remove函数:用于卸载I2C设备。当I2C总线上的设备被移除时,会调用该函数,完成设备的清理工作。 5. ioctl函数:用于实现设备的特殊操作。例如,设置I2C设备的工作模式、读取设备的状态等。 通过实现这些函数,可以编写一个完整的Linux I2C设备驱动程序。在驱动程序中,可以使用Linux内核提供的函数,例如i2c_transfer函数、i2c_smbus_read_byte函数等,来实现I2C设备的读写操作。同时,也可以使用Linux的调试工具来调试驱动程序,例如dmesg命令、insmod命令等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值