Максим MAX14830 в Linux x86/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/[email protected]/T/) заставляет меня поверить, что использование общей структуры часов не поддерживается в 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
                )
            })
        }
    }
}

person drkwood    schedule 05.10.2020    source источник
comment
В Linux нет поддержки ACPI в CCF. Прочитайте это обсуждение аналогичной проблемы с другим устройством: spinics.net/lists/linux- серийный/msg32694.html. Это может дать вам подсказку, что делать дальше.   -  person 0andriy    schedule 06.10.2020
comment
Примечание для людей, которые голосуют против и/или рекомендуют закрыть. Вы, вероятно, незнакомы с ACPI, потому что вышесказанное вполне по теме: ASL — это язык программирования. Пожалуйста, откажитесь от своих мнений.   -  person 0andriy    schedule 06.10.2020
comment
Эта серия lore.kernel.org/linux-serial / — это первый шаг. Второй что-то вроде spinics.net/lists/linux-serial/msg32696.html упоминалось ранее.   -  person 0andriy    schedule 07.10.2020
comment
А, и еще кое-что: проект meta-acpi собрал множество выдержек из SSDT, которые вы можете проверить: github.com/westeri/meta-acpi/tree/master/recipes-bsp/ (в папке edison их больше всего) .   -  person 0andriy    schedule 07.10.2020
comment
Спасибо @0andriy! Я нашел соответствующие коммиты из другого драйвера, на который вы мне указали (sc16is7xx), и теперь вы избавили меня от необходимости пытаться реплицировать их самостоятельно в драйвер max310x. Я пересоберу модуль ядра с вашими изменениями и повторю тестирование в начале следующей недели. Учитывая эти изменения, я думаю, что мой исходный блок AML уже правильный или очень близкий.   -  person drkwood    schedule 07.10.2020
comment
Да, ваш первый ASL довольно близок, но вам нужно удалить свойства clock-names и reg и изменить драйвер (после применения серии) для поддержки тактовой частоты один. Также мы принимаем PR для проекта meta-acpi (думаю, ваш материал относится к категории minnowboard-max, так как основан на BayTrail IIUC).   -  person 0andriy    schedule 07.10.2020
comment
У моей печатной платы есть проблема с компоновкой, поэтому я смогу закончить это чуть позже. Мой текущий рабочий diff размещен здесь (pastebin.com/XfL4nvFe) для всех, у кого есть похожая проблема. В итоге я оставил имена часов в качестве обязательного параметра, поскольку в драйвере есть тест частотного диапазона, который различается между генератором и кристаллом. Я больше не зацикливаюсь на том, что не могу получить часы, но из-за проблемы с печатной платой драйвер в настоящее время дает сбой при проверке устройства (он видит ID 0x00, что недопустимо).   -  person drkwood    schedule 15.10.2020
comment
Вышеупомянутая серия патчей была применена Грегом для версии 5.11. Отныне он доступен в репозитории Linux Next.   -  person 0andriy    schedule 01.11.2020


Ответы (1)


С обновлениями драйверов, предоставленными 0andriy (https://lore.kernel.org/linux-serial/[email protected]/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.

person drkwood    schedule 21.10.2020
comment
Спасибо! Не стесняйтесь отправлять код ASL в проект meta-acpi (github.com/westeri/meta-acpi). Кстати, проверьте это: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/. Будет частью v5.14-rc1. - person 0andriy; 07.07.2021
comment
Проблема с WRT IRQ, похоже, вы получили за нее -EPROBE_DEFER. Итак, по какой-то причине нет устройства (GPIO), которое должно обеспечивать прерывание. - person 0andriy; 07.07.2021