Как в ACPI объявлять устройства за мультиплексорами?

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

введите описание изображения здесь

Хотя драйверы мультиплексоров (и всего остального, находящегося непосредственно под \_SB_.PCI0.I2C1 и \_SB_.PCI0.I2C2) проверяют и работают правильно (на основе i2cdetect -y -r MUX_CH_BUS 0x29 0x29), устройства за мультиплексорами не проверяют.

Я пытался следовать этому примеру, но у меня растет подозрение, что это непроверенная чушь, я имею в виду, я почти уверен, что это даже не будет компилироваться из-за отсутствия ) после блока _CRS name.

Проблема в том, что у меня есть объекты с одинаковыми именами в разных частях моей иерархии? Судя по отладке (т. е. много printk внутри i2c-core-acpi.c), кажется, что код ACPI проверяет устройства только на MUX0.CH00 . Чтобы обойти это, я удалил все устройства, кроме одного, оставив мне это описание ASL:

Scope (\_SB_.PCI0.I2C1) {
    
    Device (MUX2)
    {
        Name (_HID, "PRP0001")
        Name (_DDN, "NXP PCA9544A I2C bus multiplexer")
        Name (_CRS, ResourceTemplate () {
            I2cSerialBus (
                0x72,
                ControllerInitiated,
                100000,
                AddressingMode7Bit, 
                "\\_SB.PCI0.I2C1",
                0x00,
                ResourceConsumer,,)
        })
        Name (_DSD, Package () {
            ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
            Package () {
                Package () {"compatible", "nxp,pca9544"},
            }
        })

        Device (CH00) {
            Name (_ADR, 0)
        }

        Device (CH01) {
            Name (_ADR, 1)
            Device (TOF1) {
                Name (_HID, "PRP0001")
                Name (_DDN, "STMicroelectronics VL53L0X laser rangefinder")
                Name (_CRS, ResourceTemplate () {
                    I2cSerialBus (
                        0x29,
                        ControllerInitiated,
                        100000,
                        AddressingMode7Bit,
                        "\\_SB.PCI0.I2C1.MUX2.CH01",
                        0x00,
                        ResourceConsumer,,)
                })
                Name (_DSD, Package () {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package () {
                        Package () {"compatible", "st,vl53l0x"},
                    }
                })
            }
        }
        
        Device (CH02) {
            Name (_ADR, 2)
        }
        
        Device (CH03) {
            Name (_ADR, 3)
        }
    }
}

Я удалил "^CH01" и заменил его на "\\_SB.PCI0.I2C1.MUX2.CH01", поскольку "^CH01" не работал на эта строка в ядре. К сожалению, это все еще не приводит к проверке оставшегося единственного датчика TOF.

Я могу подтвердить, что как в случае со всеми мультиплексорами и датчиками TOF, так и в случае с одним датчиком мультиплексора и TOF, я могу найти PRP0001:XX записей для обоих устройств в sys/bus/acpi/devices с модалиями, сформированными из совместимого свойства и имени устройства.

Есть ли у меня ошибка в моем ASL или это, возможно, ограничение ACPI в ядре Linux, где всем объектам устройств нужны уникальные имена? Будем признательны за любые предложения о том, как исследовать это дальше!

ОБНОВЛЕНИЕ: добавлена ​​информация в соответствии с комментариями:

Отладка просто отслеживает вызовы функций через i2c-core-acpi.c для двух устройств (i) USB-концентратор на I2C1 (работает правильно / проверяет) и (ii) датчик TOF под одним мультиплексоров.

Следующий патч предназначен для ядра v5.2.32 и показывает мою трассировку

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 9a3bcfcad35f..c651e6032e84 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -15,6 +15,8 @@
 
 #include "i2c-core.h"
 
+bool i2c_acpi_trace = false;
+
 struct i2c_acpi_handler_data {
        struct acpi_connection_info info;
        struct i2c_adapter *adapter;
@@ -79,6 +81,10 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
        if (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb))
                return 1;
 
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_fill_info: info->addr == 0 && resource != 0");
+       }
+
        if (lookup->index != -1 && lookup->n++ != lookup->index)
                return 1;
 
@@ -116,16 +122,33 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
            acpi_device_enumerated(adev))
                return -EINVAL;
 
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_lookup: state/present/enumerated");
+       }
+
        if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)
                return -ENODEV;
 
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_lookup: acpi_match_device_ids");
+       }
+
        memset(info, 0, sizeof(*info));
        lookup->device_handle = acpi_device_handle(adev);
 
        /* Look up for I2cSerialBus resource */
        INIT_LIST_HEAD(&resource_list);
+
        ret = acpi_dev_get_resources(adev, &resource_list,
                                     i2c_acpi_fill_info, lookup);
+
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_lookup: acpi_dev_get_resources -> %d", ret);
+       }
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_lookup: info->addr -> %x", info->addr);
+       }
+
        acpi_dev_free_resource_list(&resource_list);
 
        if (ret < 0 || !info->addr)
@@ -149,16 +172,28 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
        lookup.index = -1;
 
        ret = i2c_acpi_do_lookup(adev, &lookup);
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_get_info: i2c_acpi_do_lookup -> %d", ret);
+       }
+
        if (ret)
                return ret;
 
        if (adapter) {
                /* The adapter must match the one in I2cSerialBus() connector */
+               if(i2c_acpi_trace) {
+                       printk(KERN_ERR "i2c_acpi_get_info: adapter != NULL");
+               }
                if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle)
                        return -ENODEV;
+               if(i2c_acpi_trace) {
+                       printk(KERN_ERR "i2c_acpi_get_info: adapter->dev == lookup.adapter_handle");
+               }
        } else {
                struct acpi_device *adapter_adev;
-
+               if(i2c_acpi_trace) {
+                       printk(KERN_ERR "i2c_acpi_get_info: adapter == NULL");
+               }
                /* The adapter must be present */
                if (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev))
                        return -ENODEV;
@@ -174,6 +209,11 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
        /* Then fill IRQ number if any */
        INIT_LIST_HEAD(&resource_list);
        ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_get_info: acpi_dev_get_resources -> %d", ret);
+       }
+
        if (ret < 0)
                return -EINVAL;
 
@@ -213,11 +253,32 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
        struct i2c_adapter *adapter = data;
        struct acpi_device *adev;
        struct i2c_board_info info;
+       int ret = 0;
 
        if (acpi_bus_get_device(handle, &adev))
                return AE_OK;
 
-       if (i2c_acpi_get_info(adev, &info, adapter, NULL))
+       if(strcmp(acpi_dev_name(adev), "PRP0001:00") == 0 &&
+          strcmp(adapter->name, "Synopsys DesignWare I2C adapter") == 0) {
+          printk(KERN_ERR "--- start trace for PRP0001:00 ---");
+          i2c_acpi_trace = true;
+       }
+
+       if(strcmp(acpi_dev_name(adev), "PRP0001:02") == 0 &&
+          strcmp(adapter->name, "i2c-0-mux (chan_id 1)") == 0) {
+          printk(KERN_ERR "--- start trace for PRP0001:02 ---");
+          i2c_acpi_trace = true;
+       }
+
+       ret = i2c_acpi_get_info(adev, &info, adapter, NULL);
+
+       if(i2c_acpi_trace) {
+               printk(KERN_ERR "i2c_acpi_get_info -> %d", ret);
+               printk(KERN_ERR "--- end trace ---");
+       }
+       i2c_acpi_trace = false;
+
+       if (ret)
                return AE_OK;
 
        i2c_acpi_register_device(adapter, adev, &info);

Результатом этого во время загрузки для PRP0001: 00 (USB-концентратор) будет:

--- start trace for PRP0001:00 ---
i2c_acpi_lookup: state/present/enumerated
i2c_acpi_lookup: acpi_match_device_ids
i2c_acpi_fill_info: info->addr == 0 && resource != 0
i2c_acpi_lookup: acpi_dev_get_resources -> 0
i2c_acpi_lookup: info->addr -> 8
i2c_acpi_get_info: i2c_acpi_do_lookup -> 0
i2c_acpi_get_info: adapter != NULL
i2c_acpi_get_info: adapter->dev == lookup.adapter_handle
i2c_acpi_get_info: acpi_dev_get_resources -> 0
i2c_acpi_get_info -> 0
--- end trace ---

А для PRP0001: 02 (датчик ToF) это:

i2c i2c-0: Added multiplexed i2c bus 5
--- start trace for PRP0001:02 ---
i2c_acpi_lookup: state/present/enumerated
i2c_acpi_lookup: acpi_match_device_ids
i2c_acpi_fill_info: info->addr == 0 && resource != 0
i2c_acpi_lookup: acpi_dev_get_resources -> 0
i2c_acpi_lookup: info->addr -> 29
i2c_acpi_get_info: i2c_acpi_do_lookup -> 0
i2c_acpi_get_info: adapter != NULL
i2c_acpi_get_info: adapter->dev == lookup.adapter_handle
i2c_acpi_get_info: acpi_dev_get_resources -> 0
i2c_acpi_get_info -> 0
--- end trace ---
i2c i2c-0: Added multiplexed i2c bus 6
i2c i2c-0: Added multiplexed i2c bus 7
i2c i2c-0: Added multiplexed i2c bus 8

Таким образом, в этой ограниченной ситуации с одним мультиплексором, датчиком ToF и жестко заданным путем (т.е. без использования "^CHXX") кажется, что все работает правильно, за исключением того, что драйвер для ToF все еще не проверяет ...

Результат grep -H . /sys/bus/acpi/devices/PRP*/* для текущей конфигурации:

/sys/bus/acpi/devices/PRP0001:00/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:00/modalias:of:Nusb0TCsmsc,usb3503
/sys/bus/acpi/devices/PRP0001:00/path:\_SB_.PCI0.I2C1.USB0
/sys/bus/acpi/devices/PRP0001:00/uevent:MODALIAS=of:Nusb0TCsmsc,usb3503
/sys/bus/acpi/devices/PRP0001:01/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:01/modalias:of:Nmux2TCnxp,pca9544
/sys/bus/acpi/devices/PRP0001:01/path:\_SB_.PCI0.I2C1.MUX2
/sys/bus/acpi/devices/PRP0001:01/uevent:MODALIAS=of:Nmux2TCnxp,pca9544
/sys/bus/acpi/devices/PRP0001:02/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:02/modalias:of:Ntof1TCst,vl53l0x
/sys/bus/acpi/devices/PRP0001:02/path:\_SB_.PCI0.I2C1.MUX2.CH01.TOF1
/sys/bus/acpi/devices/PRP0001:02/uevent:MODALIAS=of:Ntof1TCst,vl53l0x
/sys/bus/acpi/devices/PRP0001:03/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:03/modalias:of:Nioe0TCnxp,pca9554
/sys/bus/acpi/devices/PRP0001:03/path:\_SB_.PCI0.I2C2.IOE0
/sys/bus/acpi/devices/PRP0001:03/uevent:MODALIAS=of:Nioe0TCnxp,pca9554
/sys/bus/acpi/devices/PRP0001:04/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:04/modalias:of:Nioe1TCnxp,pca9554
/sys/bus/acpi/devices/PRP0001:04/path:\_SB_.PCI0.I2C2.IOE1
/sys/bus/acpi/devices/PRP0001:04/uevent:MODALIAS=of:Nioe1TCnxp,pca9554
/sys/bus/acpi/devices/PRP0001:05/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:05/modalias:of:Nusb1TCsmsc,usb3503
/sys/bus/acpi/devices/PRP0001:05/path:\_SB_.PCI0.I2C2.USB1
/sys/bus/acpi/devices/PRP0001:05/uevent:MODALIAS=of:Nusb1TCsmsc,usb3503
/sys/bus/acpi/devices/PRP0001:06/hid:PRP0001
/sys/bus/acpi/devices/PRP0001:06/modalias:of:NledcTCnxp,pca9635
/sys/bus/acpi/devices/PRP0001:06/path:\_SB_.PCI0.I2C2.LEDC
/sys/bus/acpi/devices/PRP0001:06/uevent:MODALIAS=of:NledcTCnxp,pca9635

Выход ls -l /sys/bus/i2c/devices/i2c-6/

--w-------    1 root     root          4096 Aug 20 15:10 delete_device
lrwxrwxrwx    1 root     root             0 Aug 20 15:10 device -> ../../i2c-0
lrwxrwxrwx    1 root     root             0 Aug 20 15:10 firmware_node -> ../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/808622C1:00/PRP0001:01/device:3a
drwxr-xr-x    3 root     root             0 Aug 20 15:00 i2c-PRP0001:02
lrwxrwxrwx    1 root     root             0 Aug 20 15:10 mux_device -> ../i2c-PRP0001:01
-r--r--r--    1 root     root          4096 Aug 20 15:10 name
--w-------    1 root     root          4096 Aug 20 15:10 new_device
drwxr-xr-x    2 root     root             0 Aug 20 15:10 power
lrwxrwxrwx    1 root     root             0 Aug 20 15:00 subsystem -> ../../../../../bus/i2c
-rw-r--r--    1 root     root          4096 Aug 20 15:00 uevent

person mallwright    schedule 19.08.2020    source источник
comment
@ 0andriy, спасибо, что указали на этот патч. Остальные вопросы смотрите в добавлении контента после ОБНОВЛЕНИЯ   -  person mallwright    schedule 20.08.2020
comment
Думаю, да, сейчас я пытаюсь проследить путь между тем, когда устройство зарегистрировано, и тем, когда вызывается зонд, чтобы узнать, могу ли я выяснить, где что-то ломается ...   -  person mallwright    schedule 20.08.2020
comment
Хорошо, здесь что-то ломается: elixir.bootlin.com/linux/v5.2.21/source/drivers/i2c/, хотя я еще не уверен, почему. Я мог бы добавить acpi_match_table, но это не кажется подходящим для устройств PRP0001, поэтому мне нужно выяснить, почему i2c_of_match_device не возвращает совпадение ...   -  person mallwright    schedule 20.08.2020
comment
Драйвер скомпилирован / встроен, а вывод sysfs был добавлен в конце вопроса. После i2c_of_match_device (который, я думаю, должен использоваться для сопоставления устройств PRP0001) кажется, что он хочет сопоставить dev->of_node с таблицей сопоставления в драйвере ... не знаю, когда / где / если dev->of_node фактически инициализирован, хотя ...   -  person mallwright    schedule 20.08.2020
comment
Но есть ли у вас сам mux? Можете показать ls -l /sys/bus/i2c/? Можете ли вы показать i2cdetect -y -r ... для рассматриваемого автобуса? lsmod? Вроде есть MUX и устройство видит. Вы можете ls -l .../i2c-PRP0001:02?   -  person 0andriy    schedule 20.08.2020
comment
Что показывает i2cdetect -l? А что на выходе dmesg | grep i2c? Также grep -H . /sys/bus/i2c/devices/*/name   -  person 0andriy    schedule 20.08.2020
comment
Да, мультиплексор запущен и работает. Датчики на другой стороне мультиплексора могут быть обнаружены с помощью i2cdetect. Проблема заключается в сопоставлении: elixir.bootlin.com/linux/v5.2.21/source/drivers/i2c/   -  person mallwright    schedule 21.08.2020
comment
Я переместил эту часть вопроса в stackoverflow.com/questions/63519678/, так как это немного выходит за рамки темы из заданного выше вопроса   -  person mallwright    schedule 21.08.2020