Linux的I2C驱动架构

1.     linux的i2c驱动架构
linux中i2c总线的驱动分为两个部分,总线驱动(bus)和设备驱动(device)。其中总线驱动的职责,是为系统中每个i2c总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在在那里,等待设备驱动调用其函数。
设备驱动则是与挂在i2c总线上的具体的设备通讯的驱动。通过i2c总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。
1.1 总线驱动
在系统开机时,首先装载的是i2c总线驱动。一个总线驱动用于支持一条特定的i2c总线的读写。一个总线驱动通常需要两个模块,一个struct i2c_adapter和一个struct i2c_algorithm来描述:
static struct i2c_adapter pb1550_board_adapter = {
name:              pb1550 adapter,
id:                i2c_hw_au1550_psc,
algo:              null,
algo_data:         &pb1550_i2c_info,
inc_use:           pb1550_inc_use,
dec_use:           pb1550_dec_use,
client_register:   pb1550_reg,
client_unregister: pb1550_unreg,
client_count:      0,
};
这个样例挂接了一个叫做“pb1550 adapter”的驱动。但这个模块并未提供读写函数,具体的读写方法由第二个模块,struct i2c_algorithm提供。
static struct i2c_algorithm au1550_algo = {
.name         = au1550 algorithm,
.id      = i2c_algo_au1550,
.master_xfer  = au1550_xfer,
.functionality     = au1550_func,
};
i2c_adap->algo = &au1550_algo;
这个样例给上述总线驱动增加了读写“算法”。通常情况下每个i2c总线驱动都定义一个自己的读写算法,但鉴于有些总线使用相同的算法,因而可以共用同一套读写函数。本例中的驱动定义了自己的读写算法模块,起名叫“au1550 algorithm”。
全部填妥后,通过调用:
i2c_add_adapter(i2c_adap);
将这两个模块注册到操作系统里,总线驱动就算装上了。对于amd au1550,这部分已经由amd提供了。
1.2 设备驱动
如前所述,总线驱动只是提供了对一条总线的读写机制,本身并不会去做通信。通信是由i2c设备驱动来做的,设备驱动透过i2c总线同具体的设备进行通讯。一个设备驱动有两个模块来描述,struct i2c_driver和struct i2c_client。
当系统开机、i2c总线驱动装入完成后,就可以装入设备驱动了。首先装入如下结构:
static struct i2c_driver driver = {
.name           = i2c tv tuner driver,
.id             = i2c_driverid_tuner,
.flags          = i2c_df_notify,
.attach_adapter = tuner_probe,
.detach_client  = tuner_detach,
.command        = tuner_command,
};
i2c_add_driver(&driver);
这个i2c_driver一旦装入完成,其中的attach_adapter函数就会被调用。在其中可以遍历系统中的每个i2c总线驱动,探测想要访问的设备:
static int tuner_probe(struct i2c_adapter *adap)
{
return i2c_probe(adap, &addr_data, tuner_attach);
}
注意探测可能会找到多个设备,因而不仅一个i2c总线可以挂多个不同类型的设备,一个设备驱动也可以同时为挂在多个不同i2c总线上的设备服务。
每当设备驱动探测到了一个它能支持的设备,它就创建一个struct i2c_client来标识这个设备:
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &driver;
/* tell the i2c layer a new client has arrived */
err = i2c_attach_client(new_client);
if (err)
goto error;
可见,一个i2c_client代表着位于adapter总线上,地址为address,使用driver来驱动的一个设备。它将总线驱动与设备驱动,以及设备地址绑定在了一起。一个i2c_client就代表着一个i2c设备。
当得到i2c设备后,就可以直接对此设备进行读写:
/*
* the master routines are the ones normally used to transmit data to devices
* on a bus (or read from them). apart from two basic transfer functions to
* transmit one message at a time, a more complex version can be used to
* transmit an arbitrary number of messages without interruption.
*/
extern int i2c_master_send(struct i2c_client *,const char* ,int);
extern int i2c_master_recv(struct i2c_client *,char* ,int);
与 通常意义上的读写函数一样,这两个函数对i2c_client指针指定的设备,读写int个char。返回值为读写的字节数。对于我们现有的slic的驱 动,只要将最后要往总线上进行读写的数据引出传输到这两个函数中,移植工作就算完成了,我们将得到一个linux版的i2c设备驱动。

485扩展分布式IO模块
手机有种美叫华为荣耀8,惊艳不止是第一眼
索喜科技携驾舱一体化解决方案分享智能驾舱之道
发电机中性接地电阻柜的介绍
喝水机器人的制作
Linux的I2C驱动架构
手机指纹识别原理,手机指纹解锁什么原理
功率MOSFET设计–功耗计算
如何去检测电解电容是否完好,简单方法的介绍
第十一届中国电子信息博览会 | 南信国际精彩回顾
基于MC9S12XS128的蓄电池多功能充电系统设计
CIEDE 2000色差公式在在陶瓷业色差检测中的应用
8档输出的数控可调稳压电源电路
中国电力行业朝清洁化的方向发展,未来资产结构与布局成最大挑战
C2000系列DSP移相功能缺陷的分析与解决方法(一)
土壤墒情监测系统具有哪些优势和亮点
ADI展台数款工业方案的流量密码解读
预测和负延迟滤波器:你应该知道的五件事
喜田宁波与华侨大学信息学院校企合作创新模式—智能力控创新平台启动
8ms接入ChatGPT—打造乐鑫产品专属智能客服