Контроллер SPI Diolan DLN-2 на платформе x86_64 - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь использовать DLN-2 в среде x86_64 Linux (версия ядра 4.18) для предоставления контроллеров шины SPI и I2 C в пользовательское пространство, аналогично тому, как вы используете платформу ARM с DTS / DTB изменения файла. У меня возникают проблемы с определением правильного метода подключения подчиненного устройства SPI или монтирования устройства в пространство пользователя с драйвером spidev.

Модули ядра загружаются успешно, а шина SPI монтируется как spi_master. Я уверен, что сам чип работает, потому что интерфейсами I2 C (/ dev / i2 c - #) и GPIO (/ dev / gpiochip #) можно успешно управлять. Для справки, вот список всех ссылок в системном дереве Linux для «dln»:

# find /sys -name *dln*
/sys/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/dln2-i2c.1.auto
/sys/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/dln2-spi.2.auto
/sys/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/dln2-gpio.0.auto
/sys/fs/selinux/booleans/minidlna_read_generic_user_content
/sys/bus/platform/devices/dln2-i2c.1.auto
/sys/bus/platform/devices/dln2-spi.2.auto
/sys/bus/platform/devices/dln2-gpio.0.auto
/sys/bus/platform/drivers/dln2-gpio
/sys/bus/platform/drivers/dln2-gpio/dln2-gpio.0.auto
/sys/bus/platform/drivers/dln2-adc
/sys/bus/platform/drivers/dln2-spi
/sys/bus/platform/drivers/dln2-spi/dln2-spi.2.auto
/sys/bus/platform/drivers/dln2-i2c
/sys/bus/platform/drivers/dln2-i2c/dln2-i2c.1.auto
/sys/bus/usb/drivers/dln2
/sys/module/i2c_dln2
/sys/module/i2c_dln2/drivers/platform:dln2-i2c
/sys/module/industrialio_triggered_buffer/holders/dln2_adc
/sys/module/spi_dln2
/sys/module/spi_dln2/drivers/platform:dln2-spi
/sys/module/industrialio/holders/dln2_adc
/sys/module/dln2_adc
/sys/module/dln2_adc/drivers/platform:dln2-adc
/sys/module/gpio_dln2
/sys/module/gpio_dln2/drivers/platform:dln2-gpio
/sys/module/dln2
/sys/module/dln2/holders/i2c_dln2
/sys/module/dln2/holders/spi_dln2
/sys/module/dln2/holders/dln2_adc
/sys/module/dln2/holders/gpio_dln2
/sys/module/dln2/drivers/usb:dln2

Вот соответствующая часть журнала загрузки:

[    1.578110] usb 1-2: new full-speed USB device number 2 using xhci_hcd
[    1.705306] usb 1-2: New USB device found, idVendor=a257, idProduct=2013, bcdDevice= 1.00
[    1.705310] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[    1.705312] usb 1-2: Product: Diolan DLN2
[    1.705314] usb 1-2: Manufacturer: Diolan
[   10.485997] dln2 1-2:1.0: Diolan DLN2 serial 33632920
[   10.486182] usbcore: registered new interface driver dln2

И соответствующая часть дерева USB-устройств:

Bus 001 Device 002: ID a257:2013
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass       255 Vendor Specific Subclass
  bDeviceProtocol       255 Vendor Specific Protocol
  bMaxPacketSize0        64
  idVendor           0xa257
  idProduct          0x2013
  bcdDevice            1.00
  iManufacturer           1 Diolan
  iProduct                2 Diolan DLN2
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0020
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
can't get device qualifier: Resource temporarily unavailable
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

На данный момент, я предполагаю, что исправление ACPI является правильным методом. однако устройство не отображается в дереве устройств ACPI, или я не ищу правильную строку. Я предполагаю, что это будет похоже на следующее, которое я извлек из патча ядра (https://lore.kernel.org/patchwork/patch/527210/), который, похоже, с тех пор был удален из текущего ядра.

DefinitionBlock ("dln2.aml", "SSDT", 1, "INTEL", "CpuDptf", 3)
{
    Device (DLN0)
    {
        Name (_ADR, Zero)
        Name (_HID, "DLN2000")

        Device (TP40) {
            Name (_HID, "SPT0001")
            Name (_DDN, "SPI4-CS0")
            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
                    "\\DLN0.SPI0",           // SPI host controller
                    0                       // Must be 0
                )
            })
        }

    }
}

Я также пробовал правила udev, но мои знания udev невелики, поэтому они, вероятно, неверны. Ни один из них, казалось, не добился цели:

DEVPATH=="/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/dln2-spi.2.auto/spi_master/spi0", DRIVER="spidev"

DEVPATH=="/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/dln2-spi.2.auto/spi_master/spi0", KERNEL="spi-SPT0001:02", SUBSYSTEM="spi", DRIVER="spidev", ATTRS{driver_override}==""

DEVPATH=="/devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/dln2-spi.2.auto/spi_master/spi0/spi-SPT0001:02", KERNEL="spidev2.0", SUBSYSTEM="spidev", DRIVER=""

1 Ответ

1 голос
/ 25 марта 2020

Хорошо, теперь я могу ответить на вопрос.

Прежде всего, предположим, что DSDT на хост-машине, то есть выдержка из USB-контроллера хоста, выглядит следующим образом (некоторые имена могут отличаться, некоторые методы могут быть или не быть предоставлены, просто интересная часть нас):

Device (XHC)
{   
    Name (_ADR, 0x00110000)

    ...

    Device (RHUB)
    {   
        Name (_ADR, Zero)

        // GPLD: Generate Port Location Data (PLD)
        Method (GPLD, 1, Serialized) {
            Name (PCKG, Package () {
                Buffer (0x10) {}
            })

            // REV: Revision 0x02 for ACPI 5.0
            CreateField (DerefOf (Index (PCKG, Zero)), Zero, 0x07, REV)
            Store (0x02, REV)

            // VISI: Port visibility to user per port
            CreateField (DerefOf (Index (PCKG, Zero)), 0x40, One, VISI)
            Store (Arg0, VISI)
            Return (PCKG)
        }

        Device (HS01) { Name (_ADR, 1) }
        Device (HS02) { Name (_ADR, 2) }
        Device (SS01) { Name (_ADR, 3) }
        Device (SS02) { Name (_ADR, 4) }
        ...
    }
}

Важным является то, что устройства порта (HS01, SS01, et c) не имеют _UPC() или _PLD() методы. Если это так, вам нужно будет переопределить полный DSDT или обновить it и ACPI SSDT оверлеи не будут работать.

Предположим, что Diolan устройство подключено к HS02 порту USB. В этом случае мы должны предоставить следующую выдержку ACPI, либо в DSDT, либо в виде оверлея SSDT (примечание, метод GPLD(), если он отсутствует, следует скопировать из приведенной выше выдержки):

External (\_SB.PCI0.XHC.RHUB.HS02, DeviceObj)
External (\_SB.PCI0.XHC.RHUB.GPLD, MethodObj)

/*
 * We set the port to hard wired state to get the connected device
 * enumerated properly. See more details here:
 * https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/other-acpi-namespace-objects#acpi-namespace-hierarchy-and-_adr-for-embedded-usb-devices
 */

Scope (\_SB.PCI0.XHC.RHUB.HS02)
{
    Name (_UPC, Package ()
    {
        0xFF,
        0xFF,
        Zero,
        Zero,
    })

    Method (_PLD, 0, NotSerialized)
    {
            Return (GPLD (Zero))
    }

    Device (GPIO)
    {
        Name (_ADR, Zero)
        Name (_STA, 0x0F)
    }

    Device (I2C)
    {
        Name (_ADR, One)
        Name (_STA, 0x0F)
    }

    Device (SPI)
    {
        Name (_ADR, 0x02)
        Name (_STA, 0x0F)
    }
}

Примечание, этот пример теперь является частью проекта meta-acpi .

После загрузки этих таблиц мы получим все перечисленные значения, например:

$ grep -H HS02 /sys/bus/acpi/devices/device\:*/path
/sys/bus/acpi/devices/device:09/path:\_SB_.PCI0.XHC.RHUB.HS02
/sys/bus/acpi/devices/device:0e/path:\_SB_.PCI0.XHC.RHUB.HS02.GPIO
/sys/bus/acpi/devices/device:0f/path:\_SB_.PCI0.XHC.RHUB.HS02.I2C_
/sys/bus/acpi/devices/device:10/path:\_SB_.PCI0.XHC.RHUB.HS02.SPI_

$ ls -l /sys/bus/platform/devices/dln2-*/firmware_node
lrwxrwxrwx    1 root     root             0 Jan  1 00:04 /sys/bus/platform/devices/dln2-gpio.2.auto/firmware_node -> ../../../../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:07/device:08/device:09/device:0e
lrwxrwxrwx    1 root     root             0 Jan  1 00:04 /sys/bus/platform/devices/dln2-i2c.3.auto/firmware_node -> ../../../../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:07/device:08/device:09/device:0f
lrwxrwxrwx    1 root     root             0 Jan  1 00:04 /sys/bus/platform/devices/dln2-spi.4.auto/firmware_node -> ../../../../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:07/device:08/device:09/device:10

Это даст нам объект устройства мы можем подключить наши подчиненные устройства к. Итак, более подробно эта часть была дана ответ в следующих сообщениях SO:

Обратите внимание, что есть два исправления, которые делают это возможным в Linux. Один из них - a599a0fb629a («Добавить поддержку ACPI для устройств с интерфейсом USB»), а другой ожидает e3fadb35bc1b («Разрешить перечисление через ACPI»). Оба будут в v5.7-rc1.

...