前言
在之前的文章中我们分析到设备树里面添加了我的磁力计设备的信息,以及添加了我的磁力计驱动,那么有几个问题?
- 为什么设备树里添加设备,他就会调用我写的驱动的probe,而且磁力计驱动中只有一个函数i2c_add_driver,她又起到什么作用?
- 我在设备树下I2C控制器节点下添加磁力计设备信息,他和I2C client又能扯上什么关系?
- 我们知道,I2C访问肯定是控制器发起的,那么从我们写的磁力计驱动来看,我们就使用了i2c_master_send等接口,他和控制器又有什么联系呢?
以上就是我在学习中遇到的疑问,接下来就围绕着这些问题展开讨论!
本文中解答问题二。
设备树
i2c1: i2c@1c2b000 {
compatible = "allwinner,sun6i-a31-i2c";
reg = <0x01c2b000 0x400>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C1>;
resets = <&ccu RST_BUS_I2C1>;
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
hmc5883l@68{
compatible="honeywell,hmc5883l";
reg=<0x68>}
};
- 我们知道设备树中基本节点在kernel中靠platform模型联系起来
- 全志的I2C 驱动一定是靠allwinner,sun6i-a31-i2c联系
全志H5 I2C驱动探究
根据设备树plt dev 信息找到H5 I2C控制器驱动在这个目录下:drivers\i2c\busses该目录下还有很多厂家写的驱动,通过搜索得知H5使用是这个文件i2c-mv64xxx.c
驱动代码浏览
pltform_driver初始化
平台总线驱动注册,和设备树中也对应
probe
static int
mv64xxx_i2c_probe(struct platform_device *pd)
{
struct mv64xxx_i2c_data *drv_data;
struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev);
struct resource *r;
int rc;
drv_data = devm_kzalloc(&pd->dev, sizeof(struct mv64xxx_i2c_data),
GFP_KERNEL);
...//资源获取等寄存器基地址、clk
drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_DEPRECATED;
drv_data->adapter.nr = pd->id;
drv_data->adapter.dev.of_node = pd->dev.of_node;
platform_set_drvdata(pd, drv_data);
i2c_set_adapdata(&drv_data->adapter, drv_data);
mv64xxx_i2c_hw_init(drv_data);
rc = i2c_add_numbered_adapter(&drv_data->adapter))
...
static const struct i2c_algorithm mv64xxx_i2c_algo = {
.master_xfer = mv64xxx_i2c_xfer,
.functionality = mv64xxx_i2c_functionality,
};
- 这里能看到在控制器驱动中有个adapter的概念,可以类比下控制器,而他成员下面有个algo回调函数,这个就是I2C数据收发的回调,其实之前想的没错,I2C收发动作发起方确实是soc的控制器,只不过吧这个接口封装成函数指针供外部调用罢了。
- algo的mv64xxx_i2c_xfer就是收发数据的函数实体,他就是控制不同平台寄存器达到收发数据目的,所以我们在上层调用master_xfer 接口完全就实现不同平台的差异,无论什么平台,在上层接口不会变,达到去耦目的。这个I2C模型东西我们后面在讨论。
adapter
通过i2c_add_numbered_adapter接口将adapter注册进I2C子系统模型下,这个接口下会根据这个控制器节点扫描设备树其下node下的其他设备节点并注册client,所以这就解释了为啥设备树中 I2C设备信息要在,I2C控制器节点下填写。
algo
按照注册的结构得知,adapter下的algo指向特定平台的algo,且他下有实现master_xfer 方法,这个就是为了实现I2C数据读写用的接口。
mv64xxx_i2c_xfer->mv64xxx_i2c_execute_msg->mv64xxx_i2c_send_start
start以及wait_for_completion,这些就是控制本soc的寄存器读写达到发起I2C读写时序的操作,完成I2C的访问。
如果对您有用,小小支持一下吧!