i2c学习2
2.*struct i2c_driver-represent an I2C device driver
3.*@class:What kind of i2c device we instantiate(for detect)
4.*@attach_adapter:Callback for bus addition(for legacy drivers)
5.*@detach_adapter:Callback for bus removal(for legacy drivers)
6.*@probe:Callback for device binding
7.*@remove:Callback for device unbinding
8.*@shutdown:Callback for device shutdown
9.*@suspend:Callback for device suspend
10.*@resume:Callback for device resume
11.*@command:Callback for bus-wide signaling(optional)
12.*@driver:Device driver model driver
13.*@id_table:List of I2C devices supported by this driver
14.*@detect:Callback for device detection
15.*@address_list:The I2C addresses to probe(for detect)
16.*@clients:List of detected clients we created(for i2c-core use only)
17.*
18.*The driver.owner field should be set to the module owner of this driver.
19.*The https://www.360docs.net/doc/bc19076908.html, field should be set to the name of this driver.
20.*
21.*For automatic device detection,both@detect and
@address_data must
22.*be defined.@class should also be set,otherwise only devices forced
23.*with module parameters will be created.The detect function must
24.*fill at least the name field of the i2c_board_info structure it is
25.*handed upon successful detection,and possibly also the flags field.
26.*
27.*If@detect is missing,the driver will still work fine for
图2.1OMAP3630I2C控制器模块图
控制器1,2,3具有以下特征:
?兼容飞利浦I2C2.1版本
?支持标准I2C标准模式(100Kbps)和快速模式(400Kpbs)
?支持高达3.4Mbps的高速发送模式
?支持I2C2和I2C3模块的3线/2线的SCCB主从模式,I2C1模块的2线的SCCB主从模式,高达100kbit/s
?7-bit和10bit的设备地址模式
?多主控发送/从接收模式
?多主控接收/从发送模式
?联合的主机发送/接收和接收/发送模式
?内置FIFO(8,16,32,64字节大小)用于缓存读取和接收
?模块使能/关闭
?可编程的时钟
?8-bit的数据存取
?低功耗的设计
?两个DMA通道
?支持中断机制
?自动空闲机制
?空闲请求和应答握手机制
主从的发送机I2C4控制器有以下特征:
?支持高速和快速模式
?只能支持7-bit地址模式
?只支持主发送模式
关于I2C控制器的详细介绍请参考
OMAP36XX_ES1.1_NDA_TRM_V_G.pdf的第17章。
3OMAP3630I2C adapter驱动
在Linux内核中,I2C adapter驱动位于drivers/i2c/busses目录下,
14.{\
15..start=(irq),\
16..flags=IORESOURCE_IRQ,\
17.},
18.
19.static struct resource i2c_resources[][2]={
20.{I2C_RESOURCE_BUILDER(0,0)},
21.#if defined(CONFIG_ARCH_OMAP24XX)||
defined(CONFIG_ARCH_OMAP34XX)
22.{I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ)},
23.#endif
24.#if defined(CONFIG_ARCH_OMAP34XX)
25.{I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ)},
26.#endif
27.};
28.
29.#define I2C_DEV_BUILDER(bus_id,res,data)\
30.{\
31..id=(bus_id),\
https://www.360docs.net/doc/bc19076908.html,=name,\
33..num_resources=ARRAY_SIZE(res),\
34..resource=(res),\
35..dev={\
36..platform_data=(data),\
37.},\
38.}
39.
40.static u32i2c_rate[ARRAY_SIZE(i2c_resources)];
41.static struct platform_device omap_i2c_devices[]={
42.I2C_DEV_BUILDER(1,i2c_resources[0],&i2c_rate[0]),
43.#if defined(CONFIG_ARCH_OMAP24XX)||
defined(CONFIG_ARCH_OMAP34XX)
44.I2C_DEV_BUILDER(2,i2c_resources[1],&i2c_rate[1]),
45.#endif
46.#if defined(CONFIG_ARCH_OMAP34XX)
47.I2C_DEV_BUILDER(3,i2c_resources[2],&i2c_rate[2]),
48.#endif
49.};
可以看到,这边定义了三个I2C适配器的Platform device,id分别为“1,2,3”,name都为“i2c_omap”,变量resource中定义了适配器的寄存器基地址,irq中断号等。
3.1.2Platform device的注册
Platform device的注册是由内核启动后,具体产品的板级初始化完成的。xxxx项目的I2C adapter的Platform device注册过程如下图:
图3.1Platform device注册过程
函数omap_i2c_add_bus()中,通过函数platform_device_register()注册Platform device到platform bus上,代码如下:
1.static int__init omap_i2c_add_bus(int bus_id)
2.{
3.struct platform_device*pdev;
2.struct resource*res;
3.resource_size_t base,irq;
4.……
5.……
6.return platform_device_register(pdev);
7.}
注册完成后,中断号及寄存器的基地址等信息会在设备树中描述了,此后只需利用platform_get_resource等标准接口自动获取即可,实现了驱动和资源的分离。
3.2I2C adapter的Platform driver
Andrord2.1中Platform driver的注册的代码位于内核的
drivers/i2c/busses/i2c-omap.c中,该驱动的注册目的是初始化OMAP3630的I2C adapter,提供I2C总线传输的具体实现,并且向I2C core注册I2C adapter。
3.2.1Platform driver的定义
在文件drivers/i2c/busses/i2c-omap.c中,platform driver定义如下:
1.static struct platform_driver omap_i2c_driver={
2..probe=omap_i2c_probe,
3..remove=omap_i2c_remove,
4..driver={
https://www.360docs.net/doc/bc19076908.html,="i2c_omap",
2..owner=THIS_MODULE,
3.},
4.};
3.2.2Platform driver的注册
在文件drivers/i2c/busses/i2c-omap.c中,platform driver注册如下:
1./*I2C may be needed to bring up other drivers*/
2.static int__init.omap_i2c_init_driver(void)
3.{
4.return platform_driver_register(&omap_i2c_driver);
5.}
6.subsys_initcall(omap_i2c_init_driver);
通过platform_driver_register()函数注册Platform driver
omap_i2c_driver时,会扫描platform bus上的所有设备,由于匹配因子是name即"i2c_omap",而之前已经将name为"i2c_omap"的Platform device注册到platform bus上,因此匹配成功,调用函数omap_i2c_probe将设备和驱动绑定起来。
在drivers/i2c/busses/i2c-omap.c中会涉及到一个数据结构
omap_i2c_dev,这个结构定义了omap3630的I2C控制器,结构如下:
1.struct omap_i2c_dev{
2.struct device*dev;
2.void__iomem*base;/*virtual*/
3.int irq;
4.struct clk*iclk;/*Interface clock*/
5.struct clk*fclk;/*Functional clock*/
6.struct completion cmd_complete;
7.struct resource*ioarea;
8.u32speed;/*Speed of bus in Khz*/
9.u16cmd_err;
10.u8*buf;
11.size_t buf_len;
12.struct i2c_adapter adapter;
13.u8fifo_size;/*use as flag and value
14.*fifo_size==0implies no fifo
15.*if set,should be trsh+1
16.*/
17.u8rev;
18.unsigned b_hw:1;/*bad h/w fixes*/
19.unsigned idle:1;
20.u16iestate;/*Saved interrupt register*/
21.u16pscstate;
22.u16scllstate;
23.u16sclhstate;
24.u16bufstate;
25.u16syscstate;
26.u16westate;
27.};
Base对应I2C控制器寄存器的虚拟地址。
Irq对应I2C控制器的中断号。
Buf对应上层传下来的需要发送数据或者I2C控制接收到数据的缓存空间,buf_len是其大小。
Adapter对应I2C控制器的适配器结构。
U16类型的各个state变量是用于对应I2C控制器的寄存器的值。
函数omap_i2c_probe的执行流程如下图: