2024年6月12日发(作者:)

1. 几个基本概念

1.1. 设备模型

由 总线(bus_type) + 设备(device) + 驱动(device_driver) 组成,在该模型下,所有的设

备通过总线连接起来,即使有些设备没有连接到一根物理总线上,linux为其设置了一个内部的、

虚拟的platform总线,用以维持总线、驱动、设备的关系。

因此,对于实现一个linux下的设备驱动,可以划分为两大步:

1、设备注册;

2、驱动注册。

当然,其中还有一些细节问题:

1、驱动的probe函数

2、驱动和设备是怎么进行绑定的。

1.2. i2c设备驱动的几个数据结构

i2c_adapter:

每一个i2c_adapter对应一个物理上的i2c控制器,在i2c总线驱动probe函数中动态创建。通过

i2c_add_adapter注册到i2c_core。

i2c_algorithm:

i2c_algorithm中的关键函数master_xfer(),以i2c_msg为单位产生i2c访问需要的信号。不同

的平台所对应的master_xfer()是不同的,需要根据所用平台的硬件特性实现自己的xxx_xfer()方

法以填充i2c_algorithm的master_xfer指针;在A31上即是sun6i_i2c_algorithm函数。

i2c_client:

代表一个挂载到i2c总线上的i2c从设备,包含该设备所需要的数据:

该i2c从设备所依附的i2c控制器 struct i2c_adapter *adapter

该i2c从设备的驱动程序struct i2c_driver *driver

该i2c从设备的访问地址addr, name

该i2c从设备的名称name。

2. i2c总线驱动

2.1. 功能划分

从硬件功能上可划分为:i2c控制器和i2c外设(从设备)。每个i2c控制器总线上都可以挂载多

个i2c外设。Linux中对i2c控制器和外设分开管理:通过 i2c-sun6i.c 文件完成了i2c控制器

的设备注册和驱动注册;通过i2c-core.c为具体的i2c外设提供了统一的设备注册接口和驱动

注册接口,它分离了设备驱动device driver和硬件控制的实现细节(如操作i2c的寄存器)。

2.2. i2c-sun6i.c

该文件是与具体硬件平台相关的,对应于A3x系列芯片。该文件实际上是i2c总线驱动的实现,

本质上就是向内核注册i2c总线设备、注册总线驱动、实现总线传输的时序控制算法。i2c控制

器被注册为Platform设备,如下:

if (twi_used_mask & TWI0_USED_MASK)

platform_device_register(&sun6i_twi0_device);

if (twi_used_mask & TWI1_USED_MASK)

platform_device_register(&sun6i_twi1_device);

if (twi_used_mask & TWI2_USED_MASK)

platform_device_register(&sun6i_twi2_device);

if (twi_used_mask & TWI3_USED_MASK)

platform_device_register(&sun6i_twi3_device);

if (twi_used_mask)

return platform_driver_register(&sun6i_i2c_driver);

需要注意的是:设备与驱动的对应关系是多对一的;即如果设备类型是一样的,会共用同一套驱

动,因此上面代码只是注册了一次驱动platform_driver_register(&sun6i_i2c_driver)。

设备注册:

将i2c控制器设备注册为platform设备,为每一个控制器定义一个struct platform_device数

据结构,并且把.name都设置为"sun6i-i2c"(后面会通过名字进行匹配驱动的),然后是调用

platform_device_register()将设备注册到platform bus上。

设备注册完成后其直观的表现就是在文件系统下出现:/sys/bus/platform/devices/sun6i-i2c.0