linux中关于i2c驱动编写的注意事项

来源:互联网 发布:淘宝最低价规则 编辑:程序博客网 时间:2024/06/01 10:05

        最近在开发Cavium的平台,项目板子有几个i2c的device挂载在总线上。估计到将来客户可能需要相关的驱动,或者sample code,所以想着先把i2c 设备的相关驱动都准备好,以备不时之需。

        也是刚刚开始接触些driver,基本上是边学变写,再一边整理记录。这里就自己所理解的记录下来,一边以后回顾学习。

I2C驱动的一些问题:

1、新的kernel的i2c驱动结构有所变化,就目前2.6.27的版本和2.6.17的版本就存在区别,在/include/linux/i2c.h中就能发现不同。i2c_driver结构体变了,导致,在写i2c驱动的时候在不同的kernel上要有所调整。目前在想办法调整i2c驱动来兼容两种kernel。

主要区别是新的kernel的i2c_driver中没有detach_client 了。


2、i2c驱动涵盖:

a、首先,必须是驱动module,要依照驱动的结构来组织。比如:module init 、MODULE_LICENSE和makefile等。

b、其次、驱动属于字符型驱动,module init中要注册字符设备。编写最基本的字符型设备的驱动结构。

字符设备名称、主设备号major、次设备号minor

定义结构体static struct file_operations fops  ,要定义好其中的open、read、write、ioctl、release等函数指针。当然并不是所有的都必须定义。

c、然后,i2c驱动必须追随kernel中定义的方式来。

注意一下几个结构体:i2c_driver , i2c_adapter ,  i2c_client.。我所理解的定义这几个结构体是这样的:driver对应实际的设备驱动;adapter对应响应的smbus总线,比如/dev/i2c-2中,总线号是2,可以通过i2c_get_adapter(2)得到对应的adapter结构体;client则对应一个设备接口,提供给user来调用相关函数的。

其中关键是结构体i2c_driver的定义和实现了。新老kernel区别也在这边有所体现。

在旧的编写习惯中,经常使用

static struct i2c_driver temp_i2c_driver = {  
        .driver = {  
            .name = "temp_i2c_driver",  
        },   
        .attach_adapter = &temp_attach_adapter,  
        .detach_client  = &temp_detach_client,   //(新kernel中已无定义)
}; 

而且attach_adapter直接调用 i2c_probe(adap, 设备地址, 发现这个设备后要调用的i2c_detect函数),其实i2c_probe也在新kernel中不支持了。

而在新的kernel中需要有所调整。不然编译都会出现error。

最后使用i2c_add_drive将 定义的i2c_driver插入到系统i2c driver链表中。


d、其实最关键的是要完善定义的i2c client,将对应的adapter和address定义好之后,在read、write handle中就能通过client调用i2c操作函数(i2c.h中有申明)

extern s32 i2c_smbus_read_byte(struct i2c_client * client);
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
                                     u8 command, u8 value);
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                     u8 command, u16 value);





原创粉丝点击