英特尔凌动 E3900 系列上的 SPIDEV Linux 驱动程序
SPIDEV Linux Driver on Intel Atom E3900 Series
我正在尝试将 Intel E3900 系列(特别是 E3940)的 SPI #2 接口公开为 CentOS 8(内核版本 4.18)的 spidev 接口。作为回退,任何通过 C/C++ API 访问 SPI 控制器的方法都是可以接受的。
我正在尝试确定问题是必须由 BIOS 供应商解决还是我可以使用 ACPI 补丁修复。供应商 (Congatec) 声称 SPI 接口目前不支持作为用户空间实体,但我仍在等待我的问题升级到他们的工程组以确认这一点。供应商还声明 SPI 的 BIOS 设置应保留为“禁用”,但我也尝试了“PCI”和“ACPI”选项,但没有任何变化。
我试图将来自多个参考的片段合并在一起以创建 ACPI 补丁,包括:
https://www.kernel.org/doc/Documentation/acpi/initrd_table_override.txt
https://www.kernel.org/doc/html/latest/firmware-guide/acpi/enumeration.html
我已经重新编译了 CentOS 8 内核以包含所有必要的选项,并且我能够成功重建 Linux initrd(CentOS 8 中的 initramfs)。我通过 dmesg 日志确认我的修改正在启动时加载;我在日志中没有看到任何错误消息,所以我假设它已成功应用。
作为参考,这里是我确保在 (=y) 中编译的内核选项。我计划最终将内核模块与库存内核一起使用,但现在我认为这是更简单的方法。
CONFIG_MFD_INTEL_LPSS
CONFIG_MFD_INTEL_LPSS_ACPI
CONFIG_MFD_INTEL_LPSS_PCI
CONFIG_X86_INTEL_LPSS
CONFIG_SERIAL_8250_LPSS
CONFIG_PWM_LPSS
CONFIG_PWM_LPSS_PCI
CONFIG_PWM_LPSS_PLATFORM
CONFIG_SPI_PXA2XX
CONFIG_SPI_SPIDEV
CONFIG_SPI_BITBANG
当我使用以下命令转储未修改的 ACPI 设备树时,我能够看到对三种不同 SPI 总线的引用,这与它们的 BIOS 设置相关。据我所知,Intel 芯片只有两条 SPI 总线,这让我觉得这确实是需要在他们的 BIOS 中修复的问题。
acpidump >acpidump
acpixtract -a acpidump
iasl -sa *.dat
grep -i spi *.dsl
我已经尝试了几个选项来修补设备树,其中包括我找到的引用和重用 SPI#1 中的设备树配置(我假设它有效),但 none 似乎有效.由于我找到的示例来自 E3800 系列,我希望我只是有一些寄存器设置或引脚标识符错误,需要针对 E3900 系列进行更新。
作为参考,SPI#1 总线用于控制 SOM 上的其他组件,因此我也想避免将其用于一般用途。
提前感谢任何ideas/support。
DefinitionBlock ("spidev.aml", "SSDT", 2, "INTEL ", "SpiDev", 1)
{
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (FPNT)
{
Method (_HID, 0, NotSerialized) // _HID: Hardware ID
{
Return ("FPNT_DIS")
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings
{
Name (BBUF, ResourceTemplate ()
{
SpiSerialBusV2 (0x0000, PolarityLow, FourWireMode, 0x08,
ControllerInitiated, 0x002DC6C0, ClockPolarityLow,
ClockPhaseFirst, "\_SB.PCI0.SPI2",
0x00, ResourceConsumer, , Exclusive,
)
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
"\_SB.GPO1", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0043
}
GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullDefault, 0x0000,
"\_SB.GPO0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x000E
}
})
Return (BBUF) /* \_SB_.PCI0.SPI2.FPNT._CRS.BBUF */
}
}
}
}
DefinitionBlock ("spidev.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (TP0) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI test device connected to CS2")
Name (_DSD, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package (2) { "compatible", "spidev" },
}
})
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
2, // 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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
}
}
DefinitionBlock ("spidev.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (TP0) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI test device connected to CS2")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
2, // 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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
}
}
编辑:在通过 initrd
应用上述内容后添加了 dmesg 输出
[ 0.000000] BRK [0x63ef9000, 0x63ef9fff] PGTABLE
[ 0.000000] BRK [0x63efa000, 0x63efafff] PGTABLE
[ 0.000000] RAMDISK: [mem 0x3b4f6000-0x3ce5cfff]
[ 0.000000] ACPI: SSDT ACPI table found in initrd [kernel/firmware/acpi/spidev.aml][0xb7]
[ 0.000000] modified physical RAM map:
[ 0.000000] modified: [mem 0x0000000000000000-0x0000000000000fff] reserved
[ 0.000000] modified: [mem 0x0000000000001000-0x000000000003efff] usable
--
[ 0.000000] ACPI: UEFI 0x00000000798C8400 000042 (v01 ALASKA A M I 00000000 00000000)
[ 0.000000] ACPI: TPM2 0x00000000798C8450 000034 (v04 ALASKA A M I 00000001 AMI 00000000)
[ 0.000000] ACPI: WDAT 0x00000000798C8490 000104 (v01 00000000 00000000)
[ 0.000000] ACPI: Table Upgrade: install [SSDT- INTEL- SPIDEV]
[ 0.000000] ACPI: SSDT 0x00000000774A2000 0000B7 (v05 INTEL SPIDEV 00000001 INTL 20180629)
[ 0.000000] ACPI: Local APIC address 0xfee00000
[ 0.000000] No NUMA configuration found
[ 0.000000] Faking a node at [mem 0x0000000000000000-0x000000017fffffff]
--
[ 1.141553] dw-apb-uart.0: ttyS4 at MMIO 0x91326000 (irq = 4, base_baud = 115200) is a 16550A
[ 1.144263] dw-apb-uart.1: ttyS5 at MMIO 0x91324000 (irq = 5, base_baud = 115200) is a 16550A
[ 1.146886] dw-apb-uart.2: ttyS6 at MMIO 0x91322000 (irq = 6, base_baud = 115200) is a 16550A
[ 1.149799] pxa2xx-spi pxa2xx-spi.4: cs2 >= max 2
[ 1.151063] spi_master spi2: failed to add SPI device SPT0001:00 from ACPI
[ 1.153366] rdac: device handler registered
[ 1.154791] hp_sw: device handler registered
[ 1.156043] emc: device handler registered
[root@localhost ~]# ls /dev/
autofs fuse log nvram tty tty25 tty42 tty6 ttyS5 vcsa1
block gpiochip0 loop-control port tty0 tty26 tty43 tty60 ttyS6 vcsa2
bus gpiochip1 mapper ppp tty1 tty27 tty44 tty61 ttyS7 vcsa3
char gpiochip2 mcelog pps0 tty10 tty28 tty45 tty62 ttyS8 vcsa4
console gpiochip3 mei0 pps1 tty11 tty29 tty46 tty63 ttyS9 vcsa5
core hidraw0 mem ptmx tty12 tty3 tty47 tty7 uhid vcsa6
cpu hpet memory_bandwidth ptp0 tty13 tty30 tty48 tty8 uinput vfio
cpu_dma_latency hugepages mmcblk1 ptp1 tty14 tty31 tty49 tty9 urandom vga_arbiter
cs hwrng mmcblk1boot0 pts tty15 tty32 tty5 ttyS0 usbmon0 vhci
cuse i2c-0 mmcblk1boot1 random tty16 tty33 tty50 ttyS1 usbmon1 vhost-net
disk i2c-1 mmcblk1p1 raw tty17 tty34 tty51 ttyS10 usbmon2 vhost-vsock
dm-0 i2c-2 mmcblk1p2 rtc tty18 tty35 tty52 ttyS11 vcs zero
dm-1 i2c-3 mmcblk1p3 rtc0 tty19 tty36 tty53 ttyS12 vcs1
dri i2c-4 mmcblk1rpmb shm tty2 tty37 tty54 ttyS13 vcs2
drm_dp_aux0 i2c-5 mqueue snapshot tty20 tty38 tty55 ttyS14 vcs3
drm_dp_aux1 initctl net snd tty21 tty39 tty56 ttyS15 vcs4
fb0 input network_latency stderr tty22 tty4 tty57 ttyS2 vcs5
fd kmsg network_throughput stdin tty23 tty40 tty58 ttyS3 vcs6
full kvm null stdout tty24 tty41 tty59 ttyS4 vcsa
编辑:添加请求的tables.dat输出
https://pastebin.com/TBj8LRVc
编辑:添加了请求的状态输出
[root@localhost ~]# grep -H 15 /sys/bus/acpi/devices/*/status
/sys/bus/acpi/devices/device:19/status:15
/sys/bus/acpi/devices/device:1a/status:15
/sys/bus/acpi/devices/device:1d/status:15
/sys/bus/acpi/devices/device:3e/status:15
/sys/bus/acpi/devices/device:44/status:15
/sys/bus/acpi/devices/device:45/status:15
/sys/bus/acpi/devices/INT33A1:00/status:15
/sys/bus/acpi/devices/INT3452:00/status:15
/sys/bus/acpi/devices/INT3452:01/status:15
/sys/bus/acpi/devices/INT3452:02/status:15
/sys/bus/acpi/devices/INT3452:03/status:15
/sys/bus/acpi/devices/INT3511:00/status:15
/sys/bus/acpi/devices/INT3512:00/status:15
/sys/bus/acpi/devices/LNXPOWER:00/status:15
/sys/bus/acpi/devices/MSFT0101:00/status:15
/sys/bus/acpi/devices/PNP0103:00/status:15
/sys/bus/acpi/devices/PNP0C0D:00/status:15
/sys/bus/acpi/devices/PNP0C0E:00/status:15
编辑:添加请求的 lspci 输出
[root@localhost ~]# lspci -nk -s 19
00:19.0 1180: 8086:5ac2 (rev 0b)
Subsystem: 8086:7270
Kernel driver in use: intel-lpss
00:19.1 1180: 8086:5ac4 (rev 0b)
Subsystem: 8086:7270
Kernel driver in use: intel-lpss
00:19.2 1180: 8086:5ac6 (rev 0b)
Subsystem: 8086:7270
Kernel driver in use: intel-lpss
感谢0andriy!他让我越过了障碍,一路上教了我一些新命令。事实证明,我的问题的根本原因有两方面:
电路板供应商警告我不要在 BIOS 中启用 SPI#1,因为该总线用于控制 SoM 本身的项目(假设通过他们的 Linux BSP/driver ?)。我必须在 ACPI 模式下启用所有三个 SPI 接口才能加载它们并显示在 lspci -nk -s 19
输出中。
设备树更新文件有一个错误,我之前错过了这个错误,因为接口本身没有被加载。 AML 文件需要指定 Chip Select 1,而不是 2。
下面的脚本将进行所有 initrd 更改并使用 SPIDEV 公开所有三个 SPI 总线。在我正在测试的板上,SPI 总线作为 spidev1 通过。
我还需要确认E3900可以处理的最大速度,但我认为其他参数设置正确。
#!/bin/bash
#
# SCRIPT NAME: ENABLE SPIDEV ON INTEL ATOM E3900 SERIES SOC
# TARGET PLATFORM: CENTOS8_x86-64
# AUTHOR: ADAM ACKERMAN
# LICENSE: MIT
#
# REFERENCES:
# https://www.kernel.org/doc/Documentation/acpi/initrd_table_override.txt
#
# https://www.kernel.org/doc/html/latest/firmware-guide/acpi/enumeration.html
#
# Pull current kernel version
KERNEL_VER=$(cat /proc/version | cut -d " " -f 3)
# Verify current kernel includes spidev support
# NOTE: If configured as module, must be actively loaded
if [[ ! -d /sys/class/spidev ]]; then
modprobe spidev
if [[ ! -d /sys/class/spidev ]]; then
echo "Kernel does not support SPIDEV. Please enable first."
exit 1
fi
fi
# Move the backup file back to active, if exists
if [[ -f /boot/initramfs-$KERNEL_VER.img.bak ]]; then
rm -f /boot/initramfs-$KERNEL_VER.img
mv /boot/initramfs-$KERNEL_VER.img.bak /boot/initramfs-$KERNEL_VER.img
fi
# Create new temp directory and change to it
ACPI_TMP=$(mktemp -d)
cd $ACPI_TMP
# Reference commands to pull current ACPI tree
#acpidump >acpidump
#acpixtract -a acpidump
#iasl -sa *.dat
#grep -i spi *.dsl
# Paste in ASL file to enable the SPIDEV interface
cat > spidev.asl <<'_EOF'
DefinitionBlock ("spidev.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (TP10) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI1-CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // 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
)
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "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
)
})
}
}
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (TP20) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI2-CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // 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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
Device (TP21) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI2-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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
}
External (_SB_.PCI0.SPI3, DeviceObj)
Scope (\_SB.PCI0.SPI3)
{
Device (TP30) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI3-CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // 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.SPI3", // SPI host controller
0 // Must be 0
)
})
}
Device (TP31) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI3-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.SPI3", // SPI host controller
0 // Must be 0
)
})
}
}
}
_EOF
# Convert the ASL file to AML
iasl spidev.asl
# Create new directory structure to match initrd format
mkdir -p kernel/firmware/acpi
# Copy in the AML file
cp spidev.aml kernel/firmware/acpi
# Load all files into a new initrd in /boot
find kernel | cpio -H newc --create > /boot/instrumented_initrd
# Move out of the temporary directory and remove
cd ~
rm -rf $ACPI_TMP
# Merge the current initrd to the end of the one just created
cat /boot/initramfs-$KERNEL_VER.img >>/boot/instrumented_initrd
# Move the working one to a backup location
mv /boot/initramfs-$KERNEL_VER.img /boot/initramfs-$KERNEL_VER.img.bak
# Move the new one into place
mv /boot/instrumented_initrd /boot/initramfs-$KERNEL_VER.img
# Script Finished
echo "Process Complete - reboot the system for the changes to take effect."
echo "After reboot, verify success with command 'dmesg | grep -i spi'"
生成的设备列表是:
[root@localhost ~]# ls /dev/spi*
/dev/spidev1.0 /dev/spidev1.1 /dev/spidev2.0 /dev/spidev2.1 /dev/spidev3.0 /dev/spidev3.1
我正在尝试将 Intel E3900 系列(特别是 E3940)的 SPI #2 接口公开为 CentOS 8(内核版本 4.18)的 spidev 接口。作为回退,任何通过 C/C++ API 访问 SPI 控制器的方法都是可以接受的。
我正在尝试确定问题是必须由 BIOS 供应商解决还是我可以使用 ACPI 补丁修复。供应商 (Congatec) 声称 SPI 接口目前不支持作为用户空间实体,但我仍在等待我的问题升级到他们的工程组以确认这一点。供应商还声明 SPI 的 BIOS 设置应保留为“禁用”,但我也尝试了“PCI”和“ACPI”选项,但没有任何变化。
我试图将来自多个参考的片段合并在一起以创建 ACPI 补丁,包括:
https://www.kernel.org/doc/Documentation/acpi/initrd_table_override.txt
https://www.kernel.org/doc/html/latest/firmware-guide/acpi/enumeration.html
我已经重新编译了 CentOS 8 内核以包含所有必要的选项,并且我能够成功重建 Linux initrd(CentOS 8 中的 initramfs)。我通过 dmesg 日志确认我的修改正在启动时加载;我在日志中没有看到任何错误消息,所以我假设它已成功应用。
作为参考,这里是我确保在 (=y) 中编译的内核选项。我计划最终将内核模块与库存内核一起使用,但现在我认为这是更简单的方法。
CONFIG_MFD_INTEL_LPSS
CONFIG_MFD_INTEL_LPSS_ACPI
CONFIG_MFD_INTEL_LPSS_PCI
CONFIG_X86_INTEL_LPSS
CONFIG_SERIAL_8250_LPSS
CONFIG_PWM_LPSS
CONFIG_PWM_LPSS_PCI
CONFIG_PWM_LPSS_PLATFORM
CONFIG_SPI_PXA2XX
CONFIG_SPI_SPIDEV
CONFIG_SPI_BITBANG
当我使用以下命令转储未修改的 ACPI 设备树时,我能够看到对三种不同 SPI 总线的引用,这与它们的 BIOS 设置相关。据我所知,Intel 芯片只有两条 SPI 总线,这让我觉得这确实是需要在他们的 BIOS 中修复的问题。
acpidump >acpidump
acpixtract -a acpidump
iasl -sa *.dat
grep -i spi *.dsl
我已经尝试了几个选项来修补设备树,其中包括我找到的引用和重用 SPI#1 中的设备树配置(我假设它有效),但 none 似乎有效.由于我找到的示例来自 E3800 系列,我希望我只是有一些寄存器设置或引脚标识符错误,需要针对 E3900 系列进行更新。
作为参考,SPI#1 总线用于控制 SOM 上的其他组件,因此我也想避免将其用于一般用途。
提前感谢任何ideas/support。
DefinitionBlock ("spidev.aml", "SSDT", 2, "INTEL ", "SpiDev", 1)
{
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (FPNT)
{
Method (_HID, 0, NotSerialized) // _HID: Hardware ID
{
Return ("FPNT_DIS")
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings
{
Name (BBUF, ResourceTemplate ()
{
SpiSerialBusV2 (0x0000, PolarityLow, FourWireMode, 0x08,
ControllerInitiated, 0x002DC6C0, ClockPolarityLow,
ClockPhaseFirst, "\_SB.PCI0.SPI2",
0x00, ResourceConsumer, , Exclusive,
)
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
"\_SB.GPO1", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x0043
}
GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullDefault, 0x0000,
"\_SB.GPO0", 0x00, ResourceConsumer, ,
)
{ // Pin list
0x000E
}
})
Return (BBUF) /* \_SB_.PCI0.SPI2.FPNT._CRS.BBUF */
}
}
}
}
DefinitionBlock ("spidev.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (TP0) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI test device connected to CS2")
Name (_DSD, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package (2) { "compatible", "spidev" },
}
})
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
2, // 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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
}
}
DefinitionBlock ("spidev.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (TP0) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI test device connected to CS2")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
2, // 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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
}
}
编辑:在通过 initrd
应用上述内容后添加了 dmesg 输出[ 0.000000] BRK [0x63ef9000, 0x63ef9fff] PGTABLE
[ 0.000000] BRK [0x63efa000, 0x63efafff] PGTABLE
[ 0.000000] RAMDISK: [mem 0x3b4f6000-0x3ce5cfff]
[ 0.000000] ACPI: SSDT ACPI table found in initrd [kernel/firmware/acpi/spidev.aml][0xb7]
[ 0.000000] modified physical RAM map:
[ 0.000000] modified: [mem 0x0000000000000000-0x0000000000000fff] reserved
[ 0.000000] modified: [mem 0x0000000000001000-0x000000000003efff] usable
--
[ 0.000000] ACPI: UEFI 0x00000000798C8400 000042 (v01 ALASKA A M I 00000000 00000000)
[ 0.000000] ACPI: TPM2 0x00000000798C8450 000034 (v04 ALASKA A M I 00000001 AMI 00000000)
[ 0.000000] ACPI: WDAT 0x00000000798C8490 000104 (v01 00000000 00000000)
[ 0.000000] ACPI: Table Upgrade: install [SSDT- INTEL- SPIDEV]
[ 0.000000] ACPI: SSDT 0x00000000774A2000 0000B7 (v05 INTEL SPIDEV 00000001 INTL 20180629)
[ 0.000000] ACPI: Local APIC address 0xfee00000
[ 0.000000] No NUMA configuration found
[ 0.000000] Faking a node at [mem 0x0000000000000000-0x000000017fffffff]
--
[ 1.141553] dw-apb-uart.0: ttyS4 at MMIO 0x91326000 (irq = 4, base_baud = 115200) is a 16550A
[ 1.144263] dw-apb-uart.1: ttyS5 at MMIO 0x91324000 (irq = 5, base_baud = 115200) is a 16550A
[ 1.146886] dw-apb-uart.2: ttyS6 at MMIO 0x91322000 (irq = 6, base_baud = 115200) is a 16550A
[ 1.149799] pxa2xx-spi pxa2xx-spi.4: cs2 >= max 2
[ 1.151063] spi_master spi2: failed to add SPI device SPT0001:00 from ACPI
[ 1.153366] rdac: device handler registered
[ 1.154791] hp_sw: device handler registered
[ 1.156043] emc: device handler registered
[root@localhost ~]# ls /dev/
autofs fuse log nvram tty tty25 tty42 tty6 ttyS5 vcsa1
block gpiochip0 loop-control port tty0 tty26 tty43 tty60 ttyS6 vcsa2
bus gpiochip1 mapper ppp tty1 tty27 tty44 tty61 ttyS7 vcsa3
char gpiochip2 mcelog pps0 tty10 tty28 tty45 tty62 ttyS8 vcsa4
console gpiochip3 mei0 pps1 tty11 tty29 tty46 tty63 ttyS9 vcsa5
core hidraw0 mem ptmx tty12 tty3 tty47 tty7 uhid vcsa6
cpu hpet memory_bandwidth ptp0 tty13 tty30 tty48 tty8 uinput vfio
cpu_dma_latency hugepages mmcblk1 ptp1 tty14 tty31 tty49 tty9 urandom vga_arbiter
cs hwrng mmcblk1boot0 pts tty15 tty32 tty5 ttyS0 usbmon0 vhci
cuse i2c-0 mmcblk1boot1 random tty16 tty33 tty50 ttyS1 usbmon1 vhost-net
disk i2c-1 mmcblk1p1 raw tty17 tty34 tty51 ttyS10 usbmon2 vhost-vsock
dm-0 i2c-2 mmcblk1p2 rtc tty18 tty35 tty52 ttyS11 vcs zero
dm-1 i2c-3 mmcblk1p3 rtc0 tty19 tty36 tty53 ttyS12 vcs1
dri i2c-4 mmcblk1rpmb shm tty2 tty37 tty54 ttyS13 vcs2
drm_dp_aux0 i2c-5 mqueue snapshot tty20 tty38 tty55 ttyS14 vcs3
drm_dp_aux1 initctl net snd tty21 tty39 tty56 ttyS15 vcs4
fb0 input network_latency stderr tty22 tty4 tty57 ttyS2 vcs5
fd kmsg network_throughput stdin tty23 tty40 tty58 ttyS3 vcs6
full kvm null stdout tty24 tty41 tty59 ttyS4 vcsa
编辑:添加请求的tables.dat输出 https://pastebin.com/TBj8LRVc
编辑:添加了请求的状态输出
[root@localhost ~]# grep -H 15 /sys/bus/acpi/devices/*/status
/sys/bus/acpi/devices/device:19/status:15
/sys/bus/acpi/devices/device:1a/status:15
/sys/bus/acpi/devices/device:1d/status:15
/sys/bus/acpi/devices/device:3e/status:15
/sys/bus/acpi/devices/device:44/status:15
/sys/bus/acpi/devices/device:45/status:15
/sys/bus/acpi/devices/INT33A1:00/status:15
/sys/bus/acpi/devices/INT3452:00/status:15
/sys/bus/acpi/devices/INT3452:01/status:15
/sys/bus/acpi/devices/INT3452:02/status:15
/sys/bus/acpi/devices/INT3452:03/status:15
/sys/bus/acpi/devices/INT3511:00/status:15
/sys/bus/acpi/devices/INT3512:00/status:15
/sys/bus/acpi/devices/LNXPOWER:00/status:15
/sys/bus/acpi/devices/MSFT0101:00/status:15
/sys/bus/acpi/devices/PNP0103:00/status:15
/sys/bus/acpi/devices/PNP0C0D:00/status:15
/sys/bus/acpi/devices/PNP0C0E:00/status:15
编辑:添加请求的 lspci 输出
[root@localhost ~]# lspci -nk -s 19
00:19.0 1180: 8086:5ac2 (rev 0b)
Subsystem: 8086:7270
Kernel driver in use: intel-lpss
00:19.1 1180: 8086:5ac4 (rev 0b)
Subsystem: 8086:7270
Kernel driver in use: intel-lpss
00:19.2 1180: 8086:5ac6 (rev 0b)
Subsystem: 8086:7270
Kernel driver in use: intel-lpss
感谢0andriy!他让我越过了障碍,一路上教了我一些新命令。事实证明,我的问题的根本原因有两方面:
电路板供应商警告我不要在 BIOS 中启用 SPI#1,因为该总线用于控制 SoM 本身的项目(假设通过他们的 Linux BSP/driver ?)。我必须在 ACPI 模式下启用所有三个 SPI 接口才能加载它们并显示在
lspci -nk -s 19
输出中。设备树更新文件有一个错误,我之前错过了这个错误,因为接口本身没有被加载。 AML 文件需要指定 Chip Select 1,而不是 2。
下面的脚本将进行所有 initrd 更改并使用 SPIDEV 公开所有三个 SPI 总线。在我正在测试的板上,SPI 总线作为 spidev1 通过。
我还需要确认E3900可以处理的最大速度,但我认为其他参数设置正确。
#!/bin/bash
#
# SCRIPT NAME: ENABLE SPIDEV ON INTEL ATOM E3900 SERIES SOC
# TARGET PLATFORM: CENTOS8_x86-64
# AUTHOR: ADAM ACKERMAN
# LICENSE: MIT
#
# REFERENCES:
# https://www.kernel.org/doc/Documentation/acpi/initrd_table_override.txt
#
# https://www.kernel.org/doc/html/latest/firmware-guide/acpi/enumeration.html
#
# Pull current kernel version
KERNEL_VER=$(cat /proc/version | cut -d " " -f 3)
# Verify current kernel includes spidev support
# NOTE: If configured as module, must be actively loaded
if [[ ! -d /sys/class/spidev ]]; then
modprobe spidev
if [[ ! -d /sys/class/spidev ]]; then
echo "Kernel does not support SPIDEV. Please enable first."
exit 1
fi
fi
# Move the backup file back to active, if exists
if [[ -f /boot/initramfs-$KERNEL_VER.img.bak ]]; then
rm -f /boot/initramfs-$KERNEL_VER.img
mv /boot/initramfs-$KERNEL_VER.img.bak /boot/initramfs-$KERNEL_VER.img
fi
# Create new temp directory and change to it
ACPI_TMP=$(mktemp -d)
cd $ACPI_TMP
# Reference commands to pull current ACPI tree
#acpidump >acpidump
#acpixtract -a acpidump
#iasl -sa *.dat
#grep -i spi *.dsl
# Paste in ASL file to enable the SPIDEV interface
cat > spidev.asl <<'_EOF'
DefinitionBlock ("spidev.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (TP10) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI1-CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // 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
)
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "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
)
})
}
}
External (_SB_.PCI0.SPI2, DeviceObj)
Scope (\_SB.PCI0.SPI2)
{
Device (TP20) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI2-CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // 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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
Device (TP21) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI2-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.SPI2", // SPI host controller
0 // Must be 0
)
})
}
}
External (_SB_.PCI0.SPI3, DeviceObj)
Scope (\_SB.PCI0.SPI3)
{
Device (TP30) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI3-CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // 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.SPI3", // SPI host controller
0 // Must be 0
)
})
}
Device (TP31) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI3-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.SPI3", // SPI host controller
0 // Must be 0
)
})
}
}
}
_EOF
# Convert the ASL file to AML
iasl spidev.asl
# Create new directory structure to match initrd format
mkdir -p kernel/firmware/acpi
# Copy in the AML file
cp spidev.aml kernel/firmware/acpi
# Load all files into a new initrd in /boot
find kernel | cpio -H newc --create > /boot/instrumented_initrd
# Move out of the temporary directory and remove
cd ~
rm -rf $ACPI_TMP
# Merge the current initrd to the end of the one just created
cat /boot/initramfs-$KERNEL_VER.img >>/boot/instrumented_initrd
# Move the working one to a backup location
mv /boot/initramfs-$KERNEL_VER.img /boot/initramfs-$KERNEL_VER.img.bak
# Move the new one into place
mv /boot/instrumented_initrd /boot/initramfs-$KERNEL_VER.img
# Script Finished
echo "Process Complete - reboot the system for the changes to take effect."
echo "After reboot, verify success with command 'dmesg | grep -i spi'"
生成的设备列表是:
[root@localhost ~]# ls /dev/spi*
/dev/spidev1.0 /dev/spidev1.1 /dev/spidev2.0 /dev/spidev2.1 /dev/spidev3.0 /dev/spidev3.1