问题
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.
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
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)
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
)
})
}
}
}
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=""
回答1:
Okay, now I'm able to answer to the question.
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) }
...
}
}
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.
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)
}
}
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
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:
- adding i2c client devices on x86_64
- Building a i2c device controller
- spidev Linux driver on Intel Atom board
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.
来源:https://stackoverflow.com/questions/60105101/diolan-dln-2-spi-controller-on-x86-64-platform