Maxim MAX14830 в Linux x86 / ACPI

#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), которое должно обеспечивать прерывание.