Linux I2C驱动框架(超详细)

Linux I2C驱动框架

一、几个重要的对象

在讨论I2C驱动框架前,先讨论几个重要的概念

1、I2C总线

struct bus_type i2c_bus_type = {
   
   
	.name		= "i2c",
	.match		= i2c_device_match,
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
	.pm		= &i2c_device_pm_ops,
};

I2C总线对应着/bus下的一条总线,这个i2c总线结构体管理着i2c设备I2C驱动匹配删除等操作,I2C总线会调用i2c_device_match函数看I2C设备和I2C驱动是否匹配,如果匹配就调用i2c_device_probe函数,进而调用I2C驱动probe函数

特别提示:i2c_device_match会管理I2C设备I2C总线匹配规则,这将和如何编写I2C驱动程序息息相关

2、I2C驱动

struct i2c_driver {
   
   
	int (*probe)(struct i2c_client *, const struct i2c_device_id *); //probe函数
	struct device_driver driver; //表明这是一个驱动
	const struct i2c_device_id *id_table; //要匹配的从设备信息(名称)
	int (*detect)(struct i2c_client *, struct i2c_board_info *); //设备探测函数
	const unsigned short *address_list; //设备地址
	struct list_head clients; //设备链表
};

对应的是I2C驱动程序

3、I2C设备

struct i2c_client {
   
   
	unsigned short addr; //设备地址
	char name[I2C_NAME_SIZE]; //设备名称
	struct i2c_adapter *adapter; //设配器,值I2C控制器
	struct i2c_driver *driver; //设备对应的驱动
	struct device dev; //表明这是一个设备
	int irq; //中断号
	struct list_head detected; //节点
};

对应的是I2C设备

4、I2C设配器

I2C设配器是什么?

经过上面的介绍,知道有I2C驱动I2C设备,我们需要通过I2C驱动去和I2C设备通讯,这其中就需要一个I2C设配器I2C设配器对应的就是SOC上的I2C控制器

struct i2c_adapter {
   
   
	unsigned int id; //设备器的编号
	const struct i2c_algorithm *algo; //算法,发送时序
	struct device dev; //表明这是一个设备
};

其中的i2c_algorithm是算法的意思,对应的就是如何发送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, char read_write,
			   u8 command, int size, union i2c_smbus_data *data);
};

小结

I2C驱动有4个重要的东西,I2C总线I2C驱动I2C设备I2C设备器

  • I2C总线:维护着两个链表(I2C驱动、I2C设备),管理I2C设备I2C驱动的匹配和删除等
  • I2C驱动:对应的就是I2C设备的驱动程序
  • I2C设备:是具体硬件设备的一个抽象
  • I2C设配器:用于I2C驱动和I2C设备间的通用,是SOC上I2C控制器的一个抽象

以注册I2C驱动为例,简单讲解I2C总线的运行机制(I2C设备道理相同)

  • 1、注册I2C驱动
  • 2、将I2C驱动添加到I2C总线的驱动链表中
  • 3、遍历I2C总线上的设备链表,根据i2c_device_match函数进行匹配,如果匹配调用i2c_device_probe函数
  • 4、i2c_device_probe函数会调用I2C驱动probe函数

经过上面的讲解,对I2C驱动框架应该有了基本的了解了,下面通过分析内核源码来深入学习I2C驱动框架

二、内核源码分析

1、注册I2C驱动

编写I2C驱动程序时,通过调用i2c_add_driver函数来注册驱动,下面来分析这个函数发生了什么

static inline int i2c_add_driver(struct i2c_driver *driver)
{
   
   
	return i2c_register_driver(THIS_MODULE, driver);
}
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
   
   
    /*
    	struct bus_type i2c_bus_type = {
			.name		= "i2c",
			.match		= i2c_device_match,
			.probe		= i2c_device_probe,
			.remove		= i2c_device_remove,
			.shutdown	= i2c_device_shutdown,
			.pm		= &i2c_device_pm_ops,
		};
    */
    driver->driver.bus = &i2c_bus_type; // 绑定总线
    
    driver_register(&driver->driver); // 向总线注册驱动
    
    /* 遍历I2C总线上所有设备,调用__process_new_driver函数 */
    bus_for_each_dev(
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值