Linux i2c_driver probe被调用的流程分析(linux4.1.15)

  1. linux4.1.15 i2c_driver probe被调用流程
**/*linux4.1.15 i2c_driver probe被调用的流程分析*/**
i2c_add_driver(&ap3216c_driver);					//ap3216c.c中调用
	i2c_register_driver(THIS_MODULE, driver)		//drivers\i2c\i2c-core.c
		driver_register(&driver->driver);		    //drivers\base\driver.c
			bus_add_driver(drv);					//drivers\base\bus.c
				if (drv->bus->p->drivers_autoprobe) 
					driver_attach(drv);		//drivers\base\dd.c
					driver_attach(struct device_driver *drv)	//drivers\base\dd.c
						bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); //drivers\base\bus.c

					int bus_for_each_dev(struct bus_type *bus, struct device *start,
								         void *data, int (*fn)(struct device *, void *))
							error = fn(dev, data);
								fn 既:__driver_attach(struct device *dev, void *data)  //drivers\base\dd.c
										driver_match_device(drv, dev)					//drivers\base\dd.c
										|   // 调用i2c核心i2c-core.c中的总线的match匹配函数    
										|	return drv->bus->match ? drv->bus->match(dev, drv) : 1; //drivers\base\base.h
										|   .match	= i2c_device_match				//drivers\i2c\i2c-core.c
										|		if (of_driver_match_device(dev, drv))   //drivers\i2c\i2c-core.c
										|			of_match_device(drv->of_match_table, dev) //drivers\of\device.c
										|				of_match_node(matches, dev->of_node); //drivers\of\base.c
										|					__of_match_node(matches, node);   //drivers\of\base.c
										|						__of_device_is_compatible(node, matches->compatible,
										|									matches->type, matches->name); //drivers\of\base.c
										|							__of_find_property(device, "compatible", NULL);
										|
										if (!dev->driver)
											driver_probe_device(drv, dev);					//drivers\base\dd.c
												 really_probe(dev, drv);					//drivers\base\dd.c
													if (dev->bus->probe) {
    
    
														ret = dev->bus->probe(dev);	//设备的probe,在i2c核心层drivers\i2c\i2c-core.c
													}
													即:.probe = i2c_device_probe			//drivers\i2c\i2c-core.c
														//调用用户设备驱动中的probe
														status = driver->probe(client, i2c_match_id(driver->id_table, client));
														static int ap3216c_probe(struct i2c_client *client, 
																				const struct i2c_device_id *id)
														{
    
    
															...															
														}

  1. 涉及到的文件说明
I2C-core.c 核心以及/proc/bus/i2c 接口
	i2c_register_driver(THIS_MODULE, driver)
	调用 of_driver_match_device(dev, drv)
		struct bus_type i2c_bus_type = {
    
    
		.name		= "i2c",
		.match		= i2c_device_match,
		.probe		= i2c_device_probe,
	};

drivers\base\driver.c 常规驱动 API,负责驱动的操作
	driver_register(&driver->driver);

/* 主要实现的是驱动和设备的绑定,解除,以及驱动的自动探测等功能 */ 
/* 系统一启动就会自动执行 buses_init 来注册总线子系统(bus_subsys)*/ 
drivers\base\bus.c
	bus_add_driver(drv);			//将驱动关联到总线上
	bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

/* 负责实现驱动与设备的关联与释放操作的 */ 
drivers\base\dd.c 
	driver_attach(struct device_driver *drv) //同device_attach,区别是遍历的是drv->bus,即查找驱动
											 //所在的总线,将总线上的设备尝试关联成drv驱动
	__driver_attach(struct device *dev, void *data)
	driver_match_device(drv, dev)	
	driver_probe_device(drv, dev);	//驱动的绑定
	really_probe(dev, drv);			//调用really_probe函数进行绑定, 对dev创建link,实现dev和drive文件夹的链接,
									//调用dev->bus->probe或drv->probe进行探测
									//探测成功则driver_bound(dev)完成绑定

drivers\of\device.c 设备树相关,匹配设备
	of_match_device(drv->of_match_table, dev) 

drivers\of\base.c  设备树相关,匹配DTS节点
	of_match_node(matches, dev->of_node);
	__of_match_node(matches, node);  
  1. 架构(参考自网络)
Linux的I2C构架分为三个部分:
1)I2C core框架
	提供了核心数据结构的定义和相关接口函数,用来实现I2C适配器驱动和设备驱动的注册、注销管理,以及I2C通信方法上层的、与具体
	适配器无关的代码,为系统中每个I2C总线增加相应的读写方法。具体实现在/drivers/i2c目录下的i2c-core.c和i2c-dev.c。

 2) I2C总线驱动
	定义描述具体I2C总线适配器的i2c_adapter数据结构、实现在具体I2C适配器上的I2C总线通信方法,并由i2c_algorithm数据结构进行
	描述。经过I2C总线驱动的的代码,可以为我们控制I2C产生开始位、停止位、读写周期以及从设备的读写、产生ACK等。总线驱动具体实
	现在/drivers/i2c目录下busses文件夹中,例如Linux I2C GPIO总线驱动为i2c_gpio.c。总线算法在/drivers/i2c目录下algos文
	件夹中, 例如Linux I2C GPIO总线驱动算法实现为i2c_algo_bit.c。

 3) I2C 设备驱动
	是对具体I2C硬件驱动的实现。I2C 设备驱动通过I2C适配器与CPU通信。其中主要包含i2c_driver和 i2c_client数据结构,
	i2c_driver结构对应一套具体的驱动方法,例如:probe、remove、suspend等,需要自己申明。 i2c_client数据结构由内核根据具
	体的设备注册信息自动生成,设备驱动根据硬件具体情况填充。设备驱动具体实现放在/drivers/i2c目录下chips文件夹中。
  1. 驱动的编写
如何编写自己的i2c相关的驱动,参考方案:
(1)提供 I2C 适配器的硬件驱动,探测、初始化 I2C 适配器(如申请 I2C 的 I/O 地址和中断号)、驱动 CPU 控制的 I2C 适配器从硬
	件上产生各种信号以及处理 I2C 中断等。
(2)提供 I2C 适配器的 algorithm ,用具体适配器的 xxx_xfer() 函数填充 i2c_algorithm 的 master_xfer 指针,并把 
	i2c_algorithm 指针赋值给 i2c_adapter 的 algo 指针。
(3)实现 I2C 设备驱动与 i2c_driver 接口,用具体设备 yyy 的 yyy_attach_adapter() 函数指针、 yyy_detach_client() 函数指
	针和 yyy_command() 函数指针的赋值给 i2c_driver 的 attach_adapter 、 detach_adapter 和 detach_client 指针。
(4)实现 I2C 设备驱动的文件操作接口,即实现具体设备 yyy 的 yyy_read()yyy_write()yyy_ioctl() 函数等。
      上述工作中 12 属于I2C总线驱动,34 属于I2C设备驱动,做完这些工作,系统会增加两个内核模块。

猜你喜欢

转载自blog.csdn.net/weixin_40209911/article/details/108622190
今日推荐