Linux i2c驱动框架分析 (一)

news/2024/7/3 0:47:38

Linux i2c驱动框架分析 (一)
Linux i2c驱动框架分析 (二)
Linux i2c驱动框架分析 (三)
通用i2c设备驱动分析

Linux的i2c体系结构

Linux的i2c体系结构分为3个组成部分。
(1) i2c核心
i2c核心提供了i2c总线驱动和设备驱动的注册、注销方法,i2c通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。

(2) i2c总线驱动
i2c总线驱动是对i2c硬件体系结构中适配器端的实现。
i2c总线驱动主要包含了i2c适配器数据结构i2c_adapter、i2c适配器的i2c_algorithm数据结构和控制i2c适配器产生通信信号的函数。
经由i2c总线驱动的代码,我们可以控制i2c适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ack等。

(3) i2c设备驱动
i2c设备驱动是对i2c硬件体系结构中设备端的实现,设备挂接在i2c适配器上,通过i2c适配器与cpu交换数据。i2c设备驱动主要包含了数据结构i2c_driver和i2c_client,我们需要根据具体设备实现其中的成员函数。

i2c驱动框架如下图所示。
在这里插入图片描述
在Linux内核源代码中的drivers目录下包含一个i2c目录,而在i2c目录下又包含如下文件和文件夹:
在这里插入图片描述
i2c-core.c,这个文件实现了i2c核心的功能。
i2c-dev.c,实现了i2c适配器设备文件的功能,每一个i2c适配器都被分配一个设备。
busses文件夹包含了一些I2C总线的驱动,如针对S3C2410、S3C2440和S3C6410等处理器的i2c控制器驱动为i2c-s3c2410.c。
algos文件夹,实现了一些i2c总线适配器的algorithm。

主要的数据结构

i2c_adapter结构体,描述一个i2c适配器(控制器),定义如下:

struct i2c_adapter {
	struct module *owner;
	unsigned int class;		  /* classes to allow probing for */

	//总线通信方法
	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
	void *algo_data;

	/* data fields that are valid for all devices	*/
	const struct i2c_lock_operations *lock_ops;
	struct rt_mutex bus_lock;
	struct rt_mutex mux_lock;

	int timeout;			/* in jiffies */
	int retries;
	struct device dev;		/* the adapter device */

	//总线号
	int nr;

	char name[48];
	struct completion dev_released;

	struct mutex userspace_clients_lock;
	struct list_head userspace_clients;

	struct i2c_bus_recovery_info *bus_recovery_info;
	const struct i2c_adapter_quirks *quirks;
};

i2c_algorithm结构体,描述一个适配器的总线通信方法:

struct i2c_algorithm {

	//传输数据函数
	int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
			   int num);

	//SMBus传输函数
	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
			   unsigned short flags, char read_write,
			   u8 command, int size, union i2c_smbus_data *data);

	/* 这个函数返回适配器支持的功能 */
	u32 (*functionality) (struct i2c_adapter *);

#if IS_ENABLED(CONFIG_I2C_SLAVE)
	int (*reg_slave)(struct i2c_client *client);
	int (*unreg_slave)(struct i2c_client *client);
#endif
};

SMBus大部分基于i2c总线规范,SMBus不需增加额外引脚。与i2c总线相比,SMBus增加了一些新的功能特性,在访问时序也有一定的差异。

i2c_driver结构体,描述一个i2c设备驱动,定义如下:

struct i2c_driver {
	unsigned int class;

	//老式的探测函数,已不推荐使用
	int (*attach_adapter)(struct i2c_adapter *) __deprecated;

	/* 驱动与适配时,会调用probe函数 */
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
	
	......
	
	struct device_driver driver;

	//该驱动所支持的设备ID
	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_client结构体,描述一个i2c设备,定义如下:

struct i2c_client {
	unsigned short flags;		/* div., see below		*/

	//设备地址
	unsigned short addr;		

	char name[I2C_NAME_SIZE];

	//设备所挂在的控制器
	struct i2c_adapter *adapter;	/* the adapter we sit on	*/

	struct device dev;		/* the device structure		*/

	int irq;			/* irq issued by device		*/

	//通过这个链表节点,挂接在驱动的clients链表
	struct list_head detected;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
	i2c_slave_cb_t slave_cb;	/* callback for slave mode	*/
#endif
};

下面梳理一下i2c_driver、i2c_client、i2c_adapter和i2c_algorithm这4个数据结构的作用及其盘根错节的关系。

  1. i2c_adapter与i2c_algorithm
    i2c_adapter对应于物理上的一个i2c适配器,而i2c_algorithm对应一套通信方法。一个i2c适配器需要i2c_algorithm中提供的通信函数来控制适配器上产生特定的访问周期。缺少 i2c_algorithm的i2c_adapter什么也做不了,因此i2c_adapter中包含其使用的 i2c_algorithm 的指针。i2c_algorithm中的关键函数master_xfer()用于产生i2c访问周期需要的信号,以 i2c_msg为单位。i2c_msg结构体也非常关键,代码清单如下给出了它的定义:
struct i2c_msg {
	__u16 addr;	/* 设备地址	*/
	__u16 flags;
#define I2C_M_RD		0x0001	/* read data, from slave to master */
														/* I2C_M_RD is guaranteed to be 0x0001! */
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */
	__u16 len;		/* 信息长度				*/
	__u8 *buf;		/* 信息数据			*/
};
  1. i2c_driver与i2c_client
    i2c_driver对应一套驱动方法,其主要成员函数是probe()、 remove()、 suspend()、 resume()等,另外id_table是该驱动所支持的i2c设备的ID表。i2c_client对应于真实的物理设备,每个i2c设备都需要一个i2c_client来描述。i2c_driver与i2c_client的关系是一对多,一个 i2c_driver上可以支持多个同等类型的i2c_client。

  2. i2c_adpater与i2c_client
    i2c_adpater与i2c_client的关系与i2c硬件体系中适配器和设备的关系一致,即i2c_client依附于i2c_adpater。由于一个适配器上可以连接多个I2C设备,所以一个i2c_adpater也可以被多个i2c_client 依附,i2c_adpater中包括依附于它的i2c_client的链表。


http://www.niftyadmin.cn/n/3657313.html

相关文章

Linux i2c驱动框架分析 (二)

Linux i2c驱动框架分析 (一) Linux i2c驱动框架分析 (二) Linux i2c驱动框架分析 (三) 通用i2c设备驱动分析 i2c core i2c核心(drivers/i2c/i2c-core.c)中提供了一组不依赖于硬件平…

BOOT,FAT16结构

以下资料仅供参考:----------------------------------------------------------------------------------------目录项(Directory Entries)文件属性字节(File attribute byte)FAT16结构(FAT16 structure)磁盘引导记录结构(BOOT record layout)目录项(Directory Entries)offset…

Tip - SQL报表打印的空白页问题

SQL报表中一个常见问题是:在HTML格式中报表看起来还不错,但是打印出来(或者在PDF格式中)却发现每一个页面后面都跟着一个空白页。这是因为报表的设计尺寸超过了打印页面的物理尺寸。那么如何设置报表的尺寸适合打印呢?…

Linux i2c驱动框架分析 (三)

Linux i2c驱动框架分析 (一) Linux i2c驱动框架分析 (二) Linux i2c驱动框架分析 (三) 通用i2c设备驱动分析 i2c适配器驱动 i2c适配器驱动加载与卸载 i2c总线驱动模块的加载函数要完成两个工作。 初始化…

.NET 格式字符串速查

.NET编程及SQL报表中常用到数字或者日期的格式转化,那些格式字符总是记不住,索性列出来备查:Standard numeric format strings: http://msdn2.microsoft.com/en-us/library/aa720653.aspxCustom numeric format strings: http://msdn2.micros…

通用i2c设备驱动分析

Linux i2c驱动框架分析 (一) Linux i2c驱动框架分析 (二) Linux i2c驱动框架分析 (三) 通用i2c设备驱动分析 内核提供了一个通用的i2c驱动,这个驱动程序为每个适配器提供了设备文件的功能&…

Linux spi驱动框架分析(一)

本次的spi专题,主要参考:这位大佬的博客 感觉大佬们的无私奉献,而我写博客的初衷除了记录自己的学习经历之外,同时也分享给大家,分享知识。 系列文章: Linux spi驱动框架分析(一) L…

软件架构师

软件企业中有一个角色叫做软件架构师,不同公司或者不同的环境下,对该职位的定位可能不尽相同。微软首席架构师Ray Ozzie 对自己职位的一些看法,倒是给人很多启发:1. 不管是设计一座桥梁还是一幢大厦,你是在特定的情况下…