您的位置:首页 > 运维架构 > Linux

linux内核I2C子系统学习(三)

2016-04-13 23:27 423 查看


/article/5800698.html




linux内核I2C子系统学习(三)

写设备驱动:
四部曲:

构建i2c_driver
注册i2c_driver
构建i2c_client ( 第一种方法:注册字符设备驱动、第二种方法:通过板文件的i2c_board_info填充,然后注册)
注销i2c_driver

具体如下:
● 构建i2c_driver

● 注册i2c_driver

● 构建i2c_client,并注册字符设备驱动
i2c_probe在探测到目标设备后,后调用pca953x_detect,并把当时的探测地址address作为参数传入。

  
i2c_check_functionality用来判定设配器的能力,这一点非常重要。你也可以直接查看对应设配器的能力,如

  
字符驱动的具体实现

  
字符设备驱动本身没有什么好说的,这里主要想说一下,如何在驱动中调用i2c设配器帮我们完成数据传输。
目前设配器主要支持两种传输方法:smbus_xfer和master_xfer。一般来说,如果设配器支持了master_xfer那么它也可以模拟支持smbus的传输。但如果只实现smbus_xfer,则不支持一些i2c的传输。
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);
master_xfer中的参数设置,和前面的用户空间编程一致。现在只是要在驱动中构建相关的参数然后调用i2c_transfer来完成传输既可。
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
smbus_xfer中的参数设置及调用方法如下:

  
上面函数完成向芯片的地址为reg的寄存器写一个16bit的数据。i2c_smbus_write_word_data的实现如下:

  
从中可以看出smbus传输一个16位数据的方法。其它操作如:字符写、字符读、字读、块操作等,可以参考内核的i2c-core.c中提供的方法。

注释:i2c_client 信息通常在BSP的板文件中通过i2c_board_info 填充,如:
定义一个I2C设备ID为“ad7142_joystick”、地址为0x2C、中断号为IRQ_PF5的i2c_client

static struct i2c_board_info __initdata xxx_i2c_board_info[] = {
{
I2C_BOARD_INFO(“ad7142_joystick”,0x2C),
.irq = IRQ_PF5,


},


.........
};
然后注册
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
通过这个就完成了i2c_client 的注册

● 注销i2c_driver

  
顺序调用内核中注册的适配器来断开我们注册过的i2c设备。此过程通过调用i2c_driver中的attach_adapter方法完成的。具体实现形式如下:

  
其实主芯片的i2c的驱动基本上都支持啦,哈哈,所以剩下的工作量不是很大,只需完成从芯片的i2c的驱动操作就ok啦,那个只是分析如何编写的便于深入理解。
另外:

几个重要的结构体:i2c_msg(设置设备地址的)、i2c_client(从机设备的地址,一般采用平台设备的形式,用probe函数探测)、i2c_driver自己构建

几个重要的方法:i2c_add_driver添加设备、i2c_transfer用于进行I2C适配器和I2C设备之间的一组消息的交互

I2C与SCCB协议区别:从机地址因为I2C是7位地址,最后一位是读写位,而SCCB是8位地址,比如ov9650,他是SCCB协议,他的地址是0x60,那么如果挂接到I2C总线上,他的地址就变成0x30了,这样算的:
SCCB地址::: 0x60: 0 1 1 0_0 0 0 0
这个0还是地址位

I2C地址:::: 0 1 1 0_0 0 0 0最后红色的0是读写位,那么地址变成了7
位 +读写位 即 0 1 1_ 0 0 0 0 +0
读写位 ) 所以从机地址变成了0x30

linux内核I2C驱动基本上就这些了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: