Я пытаюсь закодировать следующую компоновку устройств в таблице 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
CONFIG_OF=y
это могло быть возможно, но все же вы правы насчет синтаксических ошибок в отрывке. - person 0andriy   schedule 19.08.2020acpi_match_table
, но это не кажется подходящим для устройств PRP0001, поэтому мне нужно выяснить, почемуi2c_of_match_device
не возвращает совпадение ... - person mallwright   schedule 20.08.2020i2c_of_match_device
(который, я думаю, должен использоваться для сопоставления устройств PRP0001) кажется, что он хочет сопоставитьdev->of_node
с таблицей сопоставления в драйвере ... не знаю, когда / где / еслиdev->of_node
фактически инициализирован, хотя ... - person mallwright   schedule 20.08.2020ls -l /sys/bus/i2c/
? Можете ли вы показатьi2cdetect -y -r ...
для рассматриваемого автобуса?lsmod
? Вроде есть MUX и устройство видит. Вы можетеls -l .../i2c-PRP0001:02
? - person 0andriy   schedule 20.08.2020i2cdetect -l
? А что на выходеdmesg | grep i2c
? Такжеgrep -H . /sys/bus/i2c/devices/*/name
- person 0andriy   schedule 20.08.2020i2cdetect
. Проблема заключается в сопоставлении: elixir.bootlin.com/linux/v5.2.21/source/drivers/i2c/ - person mallwright   schedule 21.08.2020