i2c 知识点总结

来源:互联网 发布:软件相机 编辑:程序博客网 时间:2024/05/18 02:33
0、 总线端:主要是mach-smdkc110.c和i2c_s3c2410.c两个文件:主要完成资源的注册,在s3c24xx_i2c_probe中创建adapter和client后总线端退出
   设备端:主要是用户写的部分 通过i2c_add_driver匹配i2c_driver的id_table中的name和 client中的name后,进一步初始化client并调用i2c_driver的probe

1、i2c_client是一开始初始化的时候就创建好的,每个adapter最大有10个client,
但是一开始初始化的i2c_client是不完整的,i2c_client通过i2c_new_device创建,
但是没有初始化他的i2c_driver成员,直到设备端匹配成功时才调用i2c_bus_type的
i2c_device_probe把他的i2c_driver成员赋值

2、 调用I2c_new_device的地方有:
i2c_new_dummy            //这个是预留的接口没有使用
i2c_sysfs_new_device
i2c_scan_static_board_info //扫描I2c_board_info 创建I2c_client
i2c_detect_address 
i2c_new_probed_device

3、 i2c_device_probe(i2c_bus_type的probe函数)跟用户驱动的probe函数不是同一个,
I2c_device_probe 会调用用户定的probe函数(即:i2c_driver的probe函数)

4、I2c-dev.c文件完全可以被看做一个I2c设备驱动,不过,他实现的一个i2c_client 
是虚拟、临时的,随着设备文件的打开而产生,并随设备文件的关闭而撤销,并没有
添加到i2c_adapter的client链表中。i2c-dev.c针对每个i2c适配器生成一个主设备号为
89的设备文件,实现了i2c_driver的成员函数以及文件操作接口,所以i2c-dev.c的主体是“i2c_drvier成员函数+字符设备驱动”————详见《Linux设备驱动开发详解》P345
用户空间的  read、write/ioctl函数直接调用此驱动文件 i2cdev_read/i2cdev_write/
i2cdev_ioctl通过ioctl进行设备地址等的配置

5、s3c24XX_i2c_probe初始化硬件适配器,总线端匹配后会调用此函数

6、宏container_of(pointer, type,member),这个宏定义在linux/kernel.h里面,第一个参数就 是指向kobject的指针,type是指嵌入kobject的结构体类型,member就是在结构体类型里面kobject的成员名

7、Linux  I2C 驱动体系结构有相当的复杂度,它主要由3 部分组成,即I2C核心、I2C总线驱动
和I2C设备驱动。I2C核心:是I2C 总线驱动和I2C设备驱动的中间枢纽,它以通用的、与 平台无关的接口实现了I2C 中设备与适配器的沟通。I2C总线驱动填充i2c_ adapter 和i2c_ algorithm 结构体,I2C设备驱动填充i2c_ driver 结构体并实现其本身所对应设 备类型的驱动。 另外,系统中i2c- dev.c文件定义的主设备号为89的设备可以方便地给应用程序提供读写I2C设备寄存器的能力,使得工程师大多数时候并不需要为具体的I2C 设备驱动定义文件操作接口。

8、匹配 platform_device和platform_driver主要看两者的name 字段是否相同。 
platform_device有直接的name成员,platform_driver的name在它的 device_driver成 员内部

9、对platform_device的定义通常在 BSP 包里面实现(即arch目录下的),在 BSP 文件中,
将platform_device归纳为一个数组,最终通过platform_add_devices()函数统一注册。
platform_add_devices()函数可以将平台设备添加到系统中。
调用platform_add_devices的地方:(init_machine)
①在common_smdk.c中smdk_machine_init的函数中
②mach-smdkv210.c的smdkv210_machine_init函数中
③mach-smdkc110.c的smdkc110_machine_init函数中、smdkc100_machine_init  !!!
④mach-smdk2440.c的smdk2440_machine_init函数中
⑤mach-smdk2410.c的smdk2410_init函数中
⑥init.c(路径:arch/arm/plat-samsung)s3c_arch_init函数中

9+、i2c_register_board_info在i2c_boardinfo.c中定义
调用i2c_register_board_info的地方:
mach-smdkc110.c的smdkc100_machine_init函数路径:arch/arm/mach-s5pc110/
mach-smdkc110.c的smdkc110_machine_init函数路径:arch/arm/mach-s5pv210/
mach-vr1000.c 的vr1000_init 函数路径:arch/arm/mach-s3c2410/
即:mach-smdkc110.c 定义并注册了i2c_board_info 

10、BSP是系统用来管理外设的部分,由两部分组成:初始化、驱动程序。所谓初始化是指从系统上电复位开始直到windkernel和usrRoot根任务启动的这段时间,系统的执行过程。驱动 程序就是一些包含I/O操作的子函数。初始化包括:CPU Init、Board Init、System Init。CPUInit初始化CPU的内部寄存器。
BoardInit初始化智能I/O的寄存器,将device打通。

11、总线驱动注册的流程主要就是: 
第一步:注册platform_device;
第二步:注册 platform_driver,然后platform 总线会让两者匹配在一起。

12、使用platform总线在驱动中大体有以下几个好处: 
a,使得设备被挂接在一个总线上,使配套的sysfs节点、设备电源管理都成为可能。 
b,  隔离了BSP和驱动。BSP 中定义platform 设备和设备使用的资源(可以使用
platform_data的形式来包括platform设备的设备),设备的具体配置信息。而在驱动 中,只需要通过通用API 去获取资源和数据,做到了板相关代码和驱动代码的分离,使得驱动具有更好的可扩展性和跨平台性。

13、分配、注册和注销SPI 主机驱动结构体的API 由SPI核心层提供: 
struct spi_master *spi_alloc_master(struct device *host, unsignedsize); 
int spi_register_master(stru ctspi_master *master); 
voidspi_unregister_master(struct spi_master*master); 
这里可能会有疑问,spi master controller 注册对应的驱动框架里的哪一层?按说, spi  机控制器已经作为platform设备都注册过了。 
这里就需要用驱动设计里面的分层思想来解释。使用到platform 总线API注册platform
总线上的控制器设备和驱动,都是 common的部分。specific 的部分,会在 platform driver注册后,在probe 函数里面基于注册的 common 部分的资源信息来具体实现。称之为spi_master的注册部分。

14、bus_add_deviec
* - Add device's busattributes.
  * - Createlinks to device's bus.
  * - Add thedevice to its bus's list of devices.

15、 platform_driver_register 中初始化s3c24xx_i2c_driver
总线端的 platform_devie和platform_driver 要匹配
设备端的 i2c_client 和 i2c_driver要匹配
具体参考bma150.c 这个就是我们要写的那部分驱动

16、i2c_add_driver /i2c_adap_s3c_init(i2c-s3c2410.c)/smdkc100_machine_init(mach-smdkc110.c)开始  

17、i2c_bus_type  在i2c-core.c
18、i2c_adapter 在i2c-core.c

19、i2c_bus_type的 i2c_device_match进行i2c_driver->id_table->name与i2c_client->name 的匹配

20、i2c_driver与i2c_client是一对多的关系,一个i2c_driver上可以支持多个同等类型的i2c_client

21、i2c_client信息通常在BSP的板文件中通过 i2c_board_info填充,如下面代码就定义了一个 了I2C设备 “ID”为“ad7142 _ joystic k ”、 地 址 为 0x2C、中断号位IRQ _ PF5 的i2c_client: 
static  struct i2c_board_info  __initdata xxx_i2c_board_info[] ={ 
#if defined(CONFIG _ JOYSTICK _AD7142) || defined(CONFIG_ JOYSTICK _ AD7142 _MODULE) 
      
             I2C_BOARD_INFO("ad7142_ joystick",0x2C), 
             .irq = IRQ_PF5, 
      }, 
... 
在I2C总线驱动i2c_bus_type的match()函数i2c_device_match() 中,会调用i2c_match_ id ()函数匹配板文件中定义的ID和i2c_driver所支持的ID表。 

22、i2c_adapter中包括依附于他的i2c_client的链表

23、i2c核心(i2c-core.c)(drivers/i2c/i2c-core.c)中提供了一组不依赖于硬件平台的接口数,这个文件一般不需要修改,但是理解其中的主要函数非常关键,因为i2c总线驱动和设备驱动之间依赖于i2c核心作为纽带。

24、i2c_driver 所在的bus为i2c_bus_type
25、i2c_bus_type的mach i2c_device_match所做的匹配的是id_table的name与client的name

26、i2c_register_driver 中的 driver_register调用过bus_for_each_dev (drv->bus, NULL, drv,__driver_attach);
而i2c_register_driver在后面又直接调用了一次 bus_for_each_dev (&i2c_bus_type, NULL,driver,__process_new_driver);

27、对于newstyle方式,需要通过i2c_register_board_info()函数注册i2c_board_info,向内核提供i2c设备的相关信息。
(在mach-smdkc110.c中的smdkc110_machine_init中调用i2c_register_board_info注册i2c_board_info)

28、i2c-dev.c文件完全可以看做一个i2c设备驱动,不过,它实现的一个i2c_client是虚拟的、临时的,随着设备文件的打开而产生,随着设备文件的关闭而撤销,并没有添加到i2c_adapter的client链表中。i2c-dev.c针对每个i2c适配器生成一个主设备号为89的设备文件,实现了i2c_driver的成员函数以及文件操作接口,所以i2c-dev.c的主体是“i2c_driver成员函数+字符设备驱动”

29、i2c核心提供的i2c_add_adapter(可能用i2c_add_numbered_adapter)函数添加这个适配器。当处理器包含多个i2c控制器时,我们通过板文件定义的platform数据中的bus_num进行区 分。

30、platform_device 和platform_drvier匹配的这两者的匹配是不要用户去主动调用的,不管用 户驱动有没有注册,只要系统起来后两者都会自动匹配, 
①i2c_s3c2410.c属于总线端驱动(2410、2440、A8都用这个文件),这是个会被自动安 装的驱动,所以里面的init函数是会被执行。
platform_drvier完成注册;会同时注册adapter,并创建静态的client
②mach_smdkc110.c属于总线设备,这个也是会自动安装的驱动,通过smdkc100_machine_init。  platform_device完成注册;
③这两个注册的时候会调用platform_bus_type里面的platform_mach完成platform的匹 配(在platform_bus_type上完成匹配),即总线端的匹配,这里匹配并完成adapter的创建之后platform的任务完成,并退出。
下一步就是用户的i2c_driver与i2c_clinet的匹配了(即设备端的匹配,他们在i2c_bus_type上匹配)

31、例如s3c2410与i2c相关的platform_driver在文件i2c-s3c2410.c里面,s3c24xx_i2c_driver,当platform_device与platform_driver匹配成功时,调用s3c24xx_i2c_probe在里面会,拿到platform_device的资源,并创建adapter和client

32、s3c24xx_i2c_probe   i2c_driver_register 最终调用了i2c_new_device

33、注意 总线级 或设备级 会共用很多函数,注意当前是platform在调用的 还是i2c的在调用的 ,两者调用时回调的函数是不同的

34、i2c_driver里面有 probe ,device_driver里面也有probe,两者有什么区别
这两个probe一般不会同时定义,像bma150里面之定义了i2c_driver的probe

35、i2c_driver的driver成员里面有name,id_table成员里面也有name ,只是为什么?
通常总线在匹配的时候(总线的mach函数里面),如果id_table存在,则先拿id_table的name去匹配,id_table不存在时才匹配driver的name,像spi_bus_type和platform_bus_type的mach函数都是这样的,而现在的i2c_bus_type只拿id_table的name进行匹配。但是还是会用到driver的name查看总线上是否已经注册过此驱动所以这两个 name应该相同。