x86_64平台上的Diolan DLN-2 SPI控制器 [英] Diolan DLN-2 SPI controller on x86_64 platform

查看:98
本文介绍了x86_64平台上的Diolan DLN-2 SPI控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在x86_64 Linux环境(内核版本4.18)中使用DLN-2向用户空间提供SPI和I2C总线控制器,这与使用ARM平台进行DTS/DTB文件修改的方式类似.我无法确定使用spidev驱动程序连接SPI从设备或将设备安装到用户空间的正确方法.

I am attempting to utilize the DLN-2 in an x86_64 Linux environment (kernel version 4.18) to provide SPI and I2C bus controllers to the userspace, in a similar manner you would using an ARM platform with DTS/DTB file modifications. I am having trouble identifying the proper method to attach a SPI slave device or mount the device to userspace with the spidev driver.

内核模块已成功加载,并且SPI总线已作为spi_master安装.我确定芯片本身可以正常工作,因为可以成功操纵I2C(/dev/i2c-#)和GPIO(/dev/gpiochip#)接口.作为参考,这是Linux系统树中"dln"的所有参考的列表:

The kernel modules are loading successfully and the SPI bus is mounted as a spi_master. I am certain the chip itself is working because the I2C (/dev/i2c-#) and GPIO (/dev/gpiochip#) interfaces can be successfully manipulated. For reference, here is a list of all references in the Linux system tree for "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

这是启动日志的匹配部分:

Here is the matching portion of the boot log:

[    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设备树的相关部分:

And the relevant portion of the usb device tree:

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/)似乎已从当前内核中删除.

At this point, I am assuming that an ACPI patch is the correct method. however, the device does not appear in the ACPI device tree, or I am not searching with the correct string. I am assuming it will be similar to the following, which I pulled from a kernel patch (https://lore.kernel.org/patchwork/patch/527210/) that appears to have since been removed from the current kernel.

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的了解很少,因此可能不正确.这些似乎都没有达到目的:

I have also tried udev rules, but my knowledge of udev is slim so they are likely incorrect. None of these appeared to have done the trick:

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=""

推荐答案

好的,现在我可以回答这个问题了.

Okay, now I'm able to answer to the question.

首先,假设主机上的DSDT(即USB主机控制器摘录)看起来像这样(某些名称可能不同,某些方法可能会或可能不会提供,只是让我们感兴趣):

First of all, assume that DSDT on the host machine, i.e. USB host controller excerpt, looks like this (some names maybe different, some methods may or may not be provided, just interesting us part):

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 等)没有没有 _UPC() _PLD()方法.如果是这样,则需要覆盖完成DSDT 升级它和ACPI SSDT覆盖将不会工作.

Important thing above is that port devices (HS01, SS01, etc) does not have _UPC() or _PLD() methods. If they are, you will need to override complete DSDT or upgrade it and ACPI SSDT overlays won't work.

假定Diolan设备已连接到 HS02 USB端口.在这种情况下,我们必须以DSDT或SSDT叠加的形式提供以下ACPI摘录(注意,如果不存在,请从上面的摘录中复制方法 GPLD()):

Assume that Diolan device is connected to HS02 USB port. In this case we have to provide the following ACPI excerpt, either in DSDT or as SSDT overlay (Note, method GPLD(), if not present, should be copied from above excerpt):

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 项目的一部分

Note, this example now is a part of meta-acpi project.

加载这些表后,我们将获得所有枚举的内容,例如:

After loading these tables we will get everything enumerated like:

$ 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帖子已经回答了这一部分的更多详细信息:

This gets us the device object we can attach our slave devices to. So, more detailed this part has been answered in the following SO posts:

注意,有两个补丁程序可以在Linux中使之成为可能.一个是 a599a0fb629a (添加对USB接口设备的ACPI支持"),一个正在等待处理 e3fadb35bc1b (允许通过ACPI枚举").两者都将在v5.7-rc1中.

Note, there are two patches to make it possible in Linux. One is a599a0fb629a ("Add ACPI support for USB interface devices") and one is pending e3fadb35bc1b ("Allow to be enumerated via ACPI"). Both will be in v5.7-rc1.

这篇关于x86_64平台上的Diolan DLN-2 SPI控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆