linux I2C设备驱动

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驱动先暂时介绍到这里。后续有补充再添加。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值