#linux-device-driver #acpi
#linux-драйвер устройства #acpi
Вопрос:
Я получаю неустранимую ошибку при попытке загрузить микросхему Maxim MAX14830 SPI-to-QuadUART в среде CentOS8 (x86_64). Используемый контроллер SPI — это Intel E3900 Atom, с помощью которого я могу успешно монтировать и взаимодействовать с использованием SPIDEV.
После рассмотрения нескольких примеров из мира ARM, я считаю, что проблема заключается в том, что я не передаю параметр «clocks» драйверу max310x, но я не смог найти подходящий пример для описания «запроса к тактовой частоте источника IC» в ACPI.
Тактовый вход чипа (вывод 45, XIN) управляется стандартным тактовым генератором, работающим на частоте 7,3728 МГц.
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (_SB.PCI0.SPI1)
{
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-names", "osc"},
Package () {"clock-frequency", 7372800},
Package () {"reg", 0},
}
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "E3900-SPI1-CS1")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
1, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
Соответствующий вывод из dmesg:
[ 1.974203] max310x spi-PRP0001:03: Cannot get clock
[ 1.975951] max310x: probe of spi-PRP0001:03 failed with error -22
Техническое описание детали можно найти здесь: https://datasheets.maximintegrated.com/en/ds/MAX14830.pdf
Любые рекомендации или соответствующие ссылки на примеры будут оценены. Спасибо!
РЕДАКТИРОВАТЬ: я нашел пример того, как ссылаться на другой объект в https://www.kernel.org/doc/html/latest/firmware-guide/acpi/dsd/leds.html ; следующий AML был выполнен правильно, но привел к панике ядра. Это обсуждение (https://lore.kernel.org/lkml/914341e7-ca94-054d-6127-522b745006b4@arm.com/T /) наводит меня на мысль, что использование common clock framework не поддерживается в ACPI, поэтому любые драйверы, которые его используют, не могут использоваться с конфигурацией ACPI _DSD.
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (_SB.PCI0.SPI1)
{
Device (CLK1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim Clock Object")
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "fixed-clock"},
Package () {"clock-cells", 0},
Package () {"clock-frequency", 7372800},
}
})
}
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
100000, // 100 kHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-names", "osc"},
Package () {"clocks", ^CLK1},
Package () {"reg", 0},
}
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "E3900-SPI1-CS1")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
1, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
Комментарии:
1. В Linux нет поддержки ACPI в CCF. Прочитайте это обсуждение аналогичной проблемы с другим устройством: spinics.net/lists/linux-serial/msg32694.html . Это может дать вам подсказку, что делать дальше.
2. Обратите внимание на людей, которые голосуют отрицательно и / или рекомендуют закрыть. Вы, вероятно, не знакомы с ACPI, потому что вышесказанное вполне по теме: ASL — это язык программирования. Пожалуйста, откажитесь от своего мнения.
3. Эта серия lore.kernel.org/linux-serial /… — это первый шаг. Второй что-то вроде spinics.net/lists/linux-serial/msg32696.html упоминалось ранее.
4. Ах, и еще одна вещь: проект meta-acpi собрал много отрывков из SSDT, которые вы можете проверить: github.com/westeri/meta-acpi/tree/master/recipes-bsp /… (большинство из них содержится в папке edison ).
5. Спасибо @0andriy! Я нашел соответствующие коммиты из другого драйвера, на который вы мне указали (sc16is7xx), и теперь вы избавили меня от необходимости самостоятельно копировать их в драйвер max310x. Я перестрою модуль ядра с вашими изменениями и проведу повторное тестирование в начале следующей недели. Учитывая эти изменения, я думаю, что мой исходный блок AML уже корректен или очень близок.
Ответ №1:
С обновлениями драйверов, предоставленными 0andriy (https://lore.kernel.org/linux-serial/20201007084635.594991-1-andy.shevchenko@gmail.com/T/#u ), я смог отобразить устройства / dev / ttyMAX, хотя мне нужно было выполнить дополнительные модификации, чтобы принудительно синхронизировать генератор; драйвер по-прежнему сбрасывал ошибку «Не удается получить часы».
Я смоделировал свой AML после этого примера (https://github.com/westeri/meta-acpi/blob/master/recipes-bsp/acpi-tables/samples/edison/sc16is7xx.asl) , что привело к следующему:
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPI", 1)
{
External (_SB_.PCI0.XHC_.RHUB.HS06.GPIO, DeviceObj)
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (_SB.PCI0.SPI1)
{
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
GpioInt (Level, ActiveLow, Exclusive, PullDefault, 0x0000,
"\_SB.PCI0.XHC.RHUB.HS06.GPIO", 0x00, ResourceConsumer, , ) { 18 }
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-frequency", 7372800},
}
})
}
}
}
Однако драйвер по-прежнему не работал в функции devm_request_threaded_irq:
[ 15.951778] max310x spi-PRP0001:00: MAX14830 ID: 0xb4
[ 15.965699] max310x spi-PRP0001:00: Reference clock set to 7372800 Hz
[ 15.968883] spi-PRP0001:00: ttyMAX0 at I/O 0x0 (irq = -517, base_baud = 460800) is a MAX14830
[ 15.972907] spi-PRP0001:00: ttyMAX1 at I/O 0x20 (irq = -517, base_baud = 460800) is a MAX14830
[ 15.985941] spi-PRP0001:00: ttyMAX2 at I/O 0x40 (irq = -517, base_baud = 460800) is a MAX14830
[ 15.990046] spi-PRP0001:00: ttyMAX3 at I/O 0x60 (irq = -517, base_baud = 460800) is a MAX14830
[ 16.009260] max310x spi-PRP0001:00: Unable to reguest IRQ -517
[ 16.021810] max310x: probe of spi-PRP0001:00 failed with error -22
Будучи новичком в C-коде, я не смог найти способ исправить проблему и в итоге просто прокомментировал ее, чтобы монтирование не было автоматически снесено.
На данный момент я могу успешно запросить их с помощью утилиты setserial и получить доступ к устройствам с помощью minicom.
[root@hwtest ~]# setserial -g /dev/ttyMAX*
/dev/ttyMAX0, UART: undefined, Port: 0x0000, IRQ: -517, Flags: low_latency
/dev/ttyMAX1, UART: undefined, Port: 0x0020, IRQ: -517, Flags: low_latency
/dev/ttyMAX2, UART: undefined, Port: 0x0040, IRQ: -517, Flags: low_latency
/dev/ttyMAX3, UART: undefined, Port: 0x0060, IRQ: -517, Flags: low_latency
Я возвращаю печатную плату обратно в EE, чтобы убедиться, что последовательные порты действительно работают (у него нет простых контрольных точек), и я обновлю этот ответ, если это не так.
РЕДАКТИРОВАТЬ: мы можем отправлять данные при настройке таким образом, но путь получения не работает, вероятно, из-за проблемы с IRQ. Я проведу повторное тестирование с ядром 5.11 и отчитаюсь. Текущее состояние соответствует версии ядра LTS 5.4.70 с ручным исправлением драйвера max310x.
Комментарии:
1. Спасибо! Не стесняйтесь отправлять ASL-код в проект meta-acpi ( github.com/westeri/meta-acpi ). Кстати, проверьте это: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git /. … Будет частью версии 5.14-rc1.
2. Проблема с IRQ, похоже, у вас есть
-EPROBE_DEFER
для этого. Итак, по какой-то причине нет устройства (GPIO), которое должно обеспечивать прерывание.