关闭

linux I2C设备驱动

578人阅读 评论(0) 收藏 举报
分类:

linux I2C设备驱动主要包括两部分:设备注册、驱动程序

1、设备注册主要涉及到一个结构体和一个注册函数:

struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned shortflags;
unsigned shortaddr;
void *platform_data;
struct dev_archdata*archdata;
int irq;
};

使用例子:

static struct i2c_board_info i2c_info[] = {
        {
                I2C_BOARD_INFO("tlv320aic3x", 0x18),//I2C地址值貌似不是很重要,及时错误,也能成功注册设备,和找到相应的驱动程序。但我估计后面的I2C的读写操作收到影响
        },
        {
                I2C_BOARD_INFO("s35390a", 0x30),
        },

}

注册函数:

i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));//表示将上面tlv320aic3x、s35390a挂载到适配器编号为‘1’的I2C总线上,一般一个设备上只有一个I2C适配器,不过还有些设备是提供了两个I2C总线接口,所以适配器应该要有两个才对,具体适配器编号,可以通过如下命令查看红色部分:

ls -l /dev

.................

drwxr-xr-x    2 root     root           60 Aug  8 00:12 i2c
lrwxrwxrwx    1 root     root            5 Aug  8 00:12 i2c-1 -> i2c/1

...............

通过上面方法,就可以完成将I2C设备挂载在I2C总线上了。


2、下面我我们讲解I2C设备对应的驱动程序:

主要结构体:

struct i2c_driver {
unsigned int class;

int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);

/* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);


/* driver model interfaces that don't relate to enumeration  */
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(struct i2c_client *);

.........................

}

这个结构体中,基本可以分为两部分,这两部分可以在不同的情况下独立使用于I2C设备驱动程序中:

第一种:

/* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
使用例子:

static const struct i2c_device_id s35390a_id[] = {
{ "s35390a", 0 },
{ }
};

static struct i2c_driver s35390a_driver = {
.driver = {
.name = "rtc-s35390a",
},
.probe = s35390a_probe,
.remove = s35390a_remove,
.id_table = s35390a_id,
};


static int __init s35390a_rtc_init(void)
{
return i2c_add_driver(&s35390a_driver);
}

在这种情况下,如果想要s35390a_probe函数被调用,则需要向系统注册I2C设备到I2C总线上,方法就是上面讲到的第一点内容。


第二种:

int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);

使用实例:

static struct i2c_driver thermostat_driver = {
.driver = {
.name = "therm_adt746x",
},
.attach_adapter= attach_thermostat,
.detrach_client = client_thermostat,
};

 i2c_add_driver(&thermostat_driver);

在这种模式中,系统加载i2c_add_driver函数后,attach_adapter指向的函数会得到立即调用,完成相关I2C设备的初始化等工作。这个相比第一种方式,就可以省去了I2C设备注册的步骤了。


其实这些东西使用很灵活,这里我在介绍另外一种使用情况:

static const struct i2c_device_id therm_adt746x_id[] = {
{ "therm_adt746x", 0 },
{ }
};


static struct i2c_driver thermostat_driver = {
.driver = {
.name = "therm_adt746x",
},
.attach_adapter= attach_thermostat,
.probe = probe_thermostat,
.remove = remove_thermostat,
.id_table = therm_adt746x_id,
}; 

i2c_add_driver(&thermostat_driver);

这种情况下,一般是在attach_adapter指向的函数被调用中,完成设备的注册工作,设备被注册到I2C总线上后,probe 指向的函数被立即调用,完成后续初始化工作。


好吧,I2C驱动先暂时介绍到这里。后续有补充再添加。






0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:101867次
    • 积分:1370
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:34篇
    • 译文:1篇
    • 评论:2条
    文章分类
    最新评论