Linux I2C内核驱动程序

时间:2017-06-06 07:44:56

标签: linux linux-kernel linux-device-driver i2c sysfs

我需要创建一个Linux内核驱动程序,通过接口板与I2C上的一堆MCU连接。因为它们的数量很多,即大约1-18,我们正在使用恩智浦/ TI I2C多路复用器。

我已经导入了NXP / TI I2C Multiplexer内核驱动程序,并将其合并到DTS文件中。我已经成功地将所有I2C多路复用器列为不同的i2c-x节点。

MCU全部使用相同的地址0x08。我创建了一个内核驱动程序,为它创建了一个hwmon + sysfs接口。 但是,insmod上的驱动程序仅触发__init功能。并且不会打扰probe()

在参考许多文档时,我只能在插入

时触发探测功能
static struct i2c_board_info xxxx_i2c_devices[] = {
  {
     I2C_BOARD_INFO("xxxx", 0x08),
  },
};

及其相应的

i2c_register_board_info(0, xxxx_i2c_devices, ARRAY_SIZE(xxxx_i2c_devices));

但是,这只会在HWMON中创建一个实例,而不是我想象的那样。我提到了https://www.kernel.org/doc/Documentation/i2c/instantiating-devices

如果没有主板init的更改,我尝试使用方法3,但内核甚至不会调用probe()并检测function(),只会调用__init司机的功能。

跟随司机 - https://github.com/1119553797/sprd-kernel-common/blob/sprdb2g_gonk4.0/drivers/hwmon/w83l785ts.c

如果需要,将发布整个内核驱动程序,以供参考使用内核3.0.8,一个使用板级更改到同一个内核的自定义板。

1 个答案:

答案 0 :(得分:1)

好的,经过广泛的谷歌搜索和修补后,不同的方法是一种解决方法。

首先在DTS中,我们可以直接在Mux寻址中分配I2C地址。对于.e.g。

i2c@0 {
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <0>;

    adc0: nau7802@2a {
        compatible = "nuvoton,nau7802";
        reg = <0x2a>;
        nuvoton,vldo = <3000>;
    };
};

i2c@1 {
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <1>;

    adc1: nau7802@2a {
        compatible = "nuvoton,nau7802";
        reg = <0x2a>;
        nuvoton,vldo = <3000>;
    };
};

i2c@2 {
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <2>;

    adc2: nau7802@2a {
        compatible = "nuvoton,nau7802";
        reg = <0x2a>;
        nuvoton,vldo = <3000>;
    };
};

然后在驱动程序中,为了识别VendorID,ProductID结构,如上例“nuvoton,nau7802”,我们必须做出以下更改: -

static const struct i2c_device_id nau7802_i2c_id[] = {
    { "nau7802", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, nau7802_i2c_id);

static const struct of_device_id nau7802_dt_ids[] = {
    { .compatible = "nuvoton,nau7802" },
    {},
};
MODULE_DEVICE_TABLE(of, nau7802_dt_ids);

static struct i2c_driver nau7802_driver = {
    .probe = nau7802_probe,
    .remove = nau7802_remove,
    .id_table = nau7802_i2c_id,
    .driver = {
       .name = "nau7802",
       .of_match_table = nau7802_dt_ids,
    },
 };

可以简单地跳过“adc1”等部分。 “MODULE_DEVICE_TABLE(of,”意思是device_tree信息,来自我可以收集的内容。

如果您找到一种不需要DTS&amp; D的更好的方法,请告诉我。 board _init changes。