Linux kernel 在x86_64上添加i2c客户端设备

Linux kernel 在x86_64上添加i2c客户端设备,linux-kernel,x86,linux-device-driver,embedded-linux,acpi,Linux Kernel,X86,Linux Device Driver,Embedded Linux,Acpi,在我的x86_64板上,有i2c总线从MFD设备出来。此i2c总线上有一些设备。我能够使用i2cdetect程序检测这些设备 # i2cdetect -y 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- --

在我的x86_64板上,有i2c总线从MFD设备出来。此i2c总线上有一些设备。我能够使用i2cdetect程序检测这些设备

# i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- 4c -- -- -- 
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
我需要内核自动检测这些设备,因此,我尝试编写i2c_board_信息,如下代码所示,但内核仍然无法自动检测这些设备

#include <linux/init.h>
#include <linux/i2c.h>

#define BUS_NUMBER      0

static struct __init i2c_board_info tst_i2c0_board_info[]  = {                   
    {
        I2C_BOARD_INFO("ltc2990", 0x4c),
    },
    {
        I2C_BOARD_INFO("24c128", 0x57),
    },
};

static int tst_i2c_board_setup(void)
{
    int ret=-1;
    ret = i2c_register_board_info(BUS_NUMBER, tst_i2c0_board_info, ARRAY_SIZE(tst_i2c0_board_info));
    return ret;
}
device_initcall(tst_i2c_board_setup);
#包括
#包括
#定义总线号0
静态结构uuu init i2c_board_info tst_i2c0_board_info[]={
{
I2C电路板信息(“ltc2990”,0x4c),
},
{
I2C电路板信息(“24c128”,0x57),
},
};
静态int tst_i2c_板设置(无效)
{
int-ret=-1;
ret=i2c_寄存器_板_信息(总线_编号、tst_i2c0_板_信息、阵列_大小(tst_i2c0_板_信息));
返回ret;
}
设备初始化调用(tst_i2c_板设置);
关于如何解决这个问题有什么建议吗?

经过讨论后,我了解到有几种方法可以做到这一点(例如,安德烈建议使用acpi表等),我使用了“i2c新探测设备”方法。以下是使用的代码:

#include <linux/init.h>
#include <linux/i2c.h>

#define BUS_NUMBER      0
#define NUM_DEVICE      2

static const unsigned short normal_i2c[][2] = {
    {0x4c, I2C_CLIENT_END},
    {0x57, I2C_CLIENT_END},
};

static struct i2c_board_info tst_i2c0_board_info[2] = {
        {I2C_BOARD_INFO("ltc2990", 0x4c), },
        {I2C_BOARD_INFO("24c128", 0x57), },
};

static int tst_i2c_board_setup(void)
{
    int i = 0;
    struct i2c_adapter *i2c_adap;

    i2c_adap = i2c_get_adapter(BUS_NUMBER);
    for(i = 0; i < NUM_DEVICE; i++)
        i2c_new_probed_device(i2c_adap, &tst_i2c0_board_info[i],
                           normal_i2c[i], NULL);
    i2c_put_adapter(i2c_adap);

    return 0;
}
late_initcall(tst_i2c_board_setup);
#包括
#包括
#定义总线号0
#定义NUM_设备2
静态常量无符号短正常_i2c[][2]={
{0x4c,I2C_客户端},
{0x57,I2C_客户端},
};
静态结构i2c电路板信息tst i2c0电路板信息[2]={
{I2C电路板信息(“ltc2990”,0x4c),},
{I2C_板信息(“24c128”,0x57),},
};
静态int tst_i2c_板设置(无效)
{
int i=0;
结构i2c_适配器*i2c_适配器;
i2c_adap=i2c_get_适配器(总线编号);
对于(i=0;i
经过讨论后,我了解到有几种方法可以做到这一点(例如,安德烈建议使用acpi表等),我使用了“i2c新探测设备”方法。以下是使用的代码:

#include <linux/init.h>
#include <linux/i2c.h>

#define BUS_NUMBER      0
#define NUM_DEVICE      2

static const unsigned short normal_i2c[][2] = {
    {0x4c, I2C_CLIENT_END},
    {0x57, I2C_CLIENT_END},
};

static struct i2c_board_info tst_i2c0_board_info[2] = {
        {I2C_BOARD_INFO("ltc2990", 0x4c), },
        {I2C_BOARD_INFO("24c128", 0x57), },
};

static int tst_i2c_board_setup(void)
{
    int i = 0;
    struct i2c_adapter *i2c_adap;

    i2c_adap = i2c_get_adapter(BUS_NUMBER);
    for(i = 0; i < NUM_DEVICE; i++)
        i2c_new_probed_device(i2c_adap, &tst_i2c0_board_info[i],
                           normal_i2c[i], NULL);
    i2c_put_adapter(i2c_adap);

    return 0;
}
late_initcall(tst_i2c_board_setup);
#包括
#包括
#定义总线号0
#定义NUM_设备2
静态常量无符号短正常_i2c[][2]={
{0x4c,I2C_客户端},
{0x57,I2C_客户端},
};
静态结构i2c电路板信息tst i2c0电路板信息[2]={
{I2C电路板信息(“ltc2990”,0x4c),},
{I2C_板信息(“24c128”,0x57),},
};
静态int tst_i2c_板设置(无效)
{
int i=0;
结构i2c_适配器*i2c_适配器;
i2c_adap=i2c_get_适配器(总线编号);
对于(i=0;i
既然您有一个支持ACPI的平台,那么最好的方法就是为给定的设备提供ASL摘录

由于Intel Galileo物联网平台,Atmel 24系列EEPROM具有自己的ACPI ID,摘录将非常简单:

定义块(“at24.aml”、“SSDT”、“5”、“at24”、“1”)
{
外部(_SB_.PCI0.I2C2,设备bj)
范围(\\ U SB.PCI0.I2C2)
{
设备(EEP0){
名称(“INT3499”)
名称(“Atmel AT24兼容EEPROM”)
名称(\u CRS,ResourceTemplate(){
I2cSerialBusV2(
0x0057,//I2C从机地址
控制器初始化,
400000,//公共汽车速度
解决这个问题,
“\\\ U SB.PCI0.I2C2”,//链接到ACPI I2C主机控制器
0
)
})
名称(_DSD,包(){
TOUID(“daffd814-6eba-4d8c-8a91-bc9bbf4aa301”),
包(){
包(){“大小”,1024},
包(){“pagesize”,32},
}
})
}
}
}
请注意,size属性是在一系列(修补程序和)中添加的

注意,目前地址宽度为硬编码的8位。如果你需要16位,你需要创建一个类似的补丁,如上所述

对于LTC2990电源监视器,您需要以下摘录:

定义块(“ltc2990.aml”、“SSDT”、“5”、“PMON”、“1”) { 外部(U SB.PCI0.I2C2,设备BJ) 范围(\\ U SB.PCI0.I2C2) { 设备(PMON) { 名称(“PRP0001”) 名称(_DDN,“线性技术LTC2990电源监视器”) 名称(\u CRS,ResourceTemplate(){ I2C串行总线( 0x4c,//总线地址 控制器初始化,//不在乎 400000,//快速模式(400 kHz) AddressingMode7Bit,//7位寻址 “\\\ U SB.PCI0.I2C2”,//I2C主机控制器 0//必须为0 ) }) 名称(_DSD,包(){ TOUID(“daffd814-6eba-4d8c-8a91-bc9bbf4aa301”), 包(){ 包(){“兼容”,“lltc,ltc2990”}, } }) } } }
注意,不幸的是,驱动程序中没有兼容的字符串,因此需要像这样添加它

在上面的示例中,
\\\u SB.PCI0.I2C2
是到I2C主机控制器的绝对路径

如何应用这些文件:

  • 首先,创建一个文件夹
mkdir-p内核/固件/acpi
  • 将文件保存在该文件夹中的
    DefinitionBlock()
    宏中提到的名称下
  • 创建未压缩的cpio归档文件并在顶部连接原始initrd:
find kernel | cpio-H newc--create>/boot/instrumented_initrd
cat/boot/initrd>>/boot/instrumented_initrd
有关更多详细信息,请参阅

其他的例子和描述背后的想法可以在一些垫子上找到