Я согласен, это исправлено на скорую руку. Я буду использовать метод, основанный на ACPI.

ей плате x86_64 с устройства MFD выходит шина i2c. На этой шине 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_info, как показано в приведенном ниже коде. Но, тем не менее, ядро не может обнаружить эти устройства автоматически.

#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);

Любые предложения о том, как я могу решить эту проблему?

 rk182508 сент. 2017 г., 07:54
@ Я проверял оба сценария, т.е. звонил до и после регистрации на автобусе 0; изменив device_initcall на arch_initcall. Это не помогает
 Ash08 сент. 2017 г., 07:31
вызывается ли tst_i2c_board_setup () после регистрации шины I2C 0
 0andriy08 сент. 2017 г., 16:43
Для этого вам нужно использовать ACPI. Я бы ответил на это с примерами после моего отпуска, а пока просто Google длямета-ACPI проект на Github, чтобы получить оригинальную идею.

Ответы на вопрос(2)

После прохожденияДокументация / I2C / инстанцирование-устройствоЯ понимаю, что есть несколько способов сделать то же самое (например, как0andriy предложил использовать таблицу acpi и т. д.), я использовал метод «i2c_new_probed_device». Ниже используется код:

#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);
 rk182523 сент. 2017 г., 16:18
Я согласен, это исправлено на скорую руку. Я буду использовать метод, основанный на ACPI.
 0andriy22 сент. 2017 г., 17:53
Пока он работает, это злоупотребление платформами с поддержкой ACPI.
Решение Вопроса

лучший подход - предоставить выдержки ASL для данных устройств.

Благодаря платформе Intel Galileo для IoT EEPROM серии Atmel 24 имеет собственный идентификатор ACPI, и выдержка будет простой:

DefinitionBlock ("at24.aml", "SSDT", 5, "", "AT24", 1)
{
    External (_SB_.PCI0.I2C2, DeviceObj)

    Scope (\_SB.PCI0.I2C2)
    {
        Device (EEP0) {
            Name (_HID, "INT3499")
            Name (_DDN, "Atmel AT24 compatible EEPROM")
            Name (_CRS, ResourceTemplate () {
                I2cSerialBusV2 (
                    0x0057,              // I2C Slave Address
                    ControllerInitiated,
                    400000,              // Bus speed
                    AddressingMode7Bit,
                    "\\_SB.PCI0.I2C2",   // Link to ACPI I2C host controller
                    0
                )
            })

            Name (_DSD, Package () {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
                    Package () {"size", 1024},
                    Package () {"pagesize", 32},
                }
            })
        }
    }
}

Обратите вниманиеразмер свойство добавляется вожидающие патч серии серия (патчиdt-bindings: добавить свойство размера "eeprom" а такжеeeprom: at24: добавлена поддержка для получения свойства устройства eeprom "size").

Обратите внимание, что ширина адреса на данный момент жестко запрограммирована на 8 бит. В случае, если вам нужно иметь 16-битную версию, вам нужно создать патчи, аналогичные упомянутым выше.

Для монитора мощности LTC2990 вам понадобится следующая выдержка:

DefinitionBlock ("ltc2990.aml", "SSDT", 5, "", "PMON", 1)
{
    External (\_SB_.PCI0.I2C2, DeviceObj)

    Scope (\_SB.PCI0.I2C2)
    {
        Device (PMON)
        {
            Name (_HID, "PRP0001")
            Name (_DDN, "Linear Technology LTC2990 power monitor")
            Name (_CRS, ResourceTemplate () {
                I2cSerialBus (
                    0x4c,                   // Bus address
                    ControllerInitiated,    // Don't care
                    400000,                 // Fast mode (400 kHz)
                    AddressingMode7Bit,     // 7-bit addressing
                    "\\_SB.PCI0.I2C2",      // I2C host controller
                    0                       // Must be 0
                )
            })

            Name (_DSD, Package () {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package () {
                    Package () {"compatible", "lltc,ltc2990"},
                }
            })
        }
    }
}

Обратите внимание, к сожалению, в драйвере нет совместимой строки, поэтому нужно добавить ее какэто сделано здесь.

В приведенных выше примерах\\_SB.PCI0.I2C2 это абсолютный путь к хост-контроллеру I2C.

Как применить эти файлы:

Прежде всего, создайте папку
mkdir -p kernel/firmware/acpi
сохранить файлы под именами, указанными вDefinitionBlock() макрос в этой папкесоздайте несжатый архив cpio и объедините оригинальный initrd сверху:
find kernel | cpio -H newc --create > /boot/instrumented_initrd
cat /boot/initrd >> /boot/instrumented_initrd

Более подробная информация доступна вSSDT-overlays.txt.

Другие примеры и описание идеи можно найти настраница мета-акпи GitHubНекоторые материалы с которых скопированы здесь.

 0andriy11 мар. 2019 г., 08:17
@InsaneCoder, другой способ - загрузить их через configfs. Смотрите эту ссылку:github.com/torvalds/linux/blob/master/Documentation/acpi/... (вот патч, который принес егоpatchwork.kernel.org/patch/9221305)
 Insane Coder10 мар. 2019 г., 14:08
Что делать, если я не хочу использовать initrd. Я напрямую загружаю ядро из GRUB. В таком случае, как я могу применить эти файлы? Не могли бы вы помочь.

Ваш ответ на вопрос