基于ACPI配置UDOO x86平台I2C外设及驱动的技术咨询
Hey there, let's walk through how to implement the ACPI SSDT configuration for your UDOO x86 + custom PCB setup. Since Ubuntu 18.04.2 on UDOO x86 relies on ACPI (not device trees) for hardware enumeration, we'll fix and extend your SSDT template to cover all your I2C chips, their interrupts, sub-buses, and downstream devices.
1. Start with the UDOO x86's Root I2C Bus
First, you need to reference the existing I2C bus on your UDOO x86 (we'll assume you're using I2C1; adjust if you're using the second available bus). Here's the base framework for your SSDT:
DefinitionBlock ("", "SSDT", 2, "ACPI", "CUSTPCB", 0x00000001) { // Reference the UDOO x86's I2C controller (adjust path if your bus uses a different ACPI node) External (_SB.PCI0.I2C1, DeviceObj) Scope (_SB.PCI0.I2C1) { // We'll add our PCA9543 and downstream devices here } }
Tip: To find the exact ACPI path for your UDOO x86's I2C buses, run
lspci -voracpidumpand parse the output to locate the I2C controller nodes.
2. Configure the PCA9543 Bus Switch with GPIO Interrupt
Next, declare the PCA9543 under the root I2C bus, set its I2C address, and wire up the GPIO interrupt. Let's assume your PCA9543 uses address 0x70 (adjust based on your hardware's A0/A1 pin wiring) and is connected to GPIO GPIO45 (replace with your actual GPIO pin on UDOO x86):
Scope (_SB.PCI0.I2C1) { Device (PCA9) // PCA9543 device node { Name (_HID, "PRP0001") // Generic I2C device ID for driver matching Name (_CID, "PCA9543") // Optional: Exact chip ID to help driver detection Name (_ADR, 0x70) // I2C address of PCA9543 // Define GPIO interrupt resource Name (_CRS, ResourceTemplate () { Interrupt (ResourceConsumer, Edge, ActiveLow, Exclusive, ,, ) { 0x0000002D // Replace with your GPIO's actual IRQ number } }) // Declare PCA9543's channels Device (CH0) // Channel 0: Connected to SC18IS602B and SC16IS741A { Name (_ADR, 0x00) // PCA9543 channel 0 address offset // Downstream devices will go here } Device (CH1) // Channel 1: Reserved for expansion { Name (_ADR, 0x01) // PCA9543 channel 1 address offset } } }
Important: To get the correct IRQ for your GPIO, export the pin first with
echo 45 | sudo tee /sys/class/gpio/export, then runcat /sys/class/gpio/gpio45/irqto get the IRQ number.
3. Add SC18IS602B (I2C-to-SPI) to PCA9543 Channel 0
Now we'll declare the SC18IS602B under channel 0, set its I2C address, and define the SPI bus it provides. Let's use address 0x28 (adjust based on your hardware's A0/A1 pins):
Device (CH0) { Name (_ADR, 0x00) Device (SPIB) // SC18IS602B device node { Name (_HID, "PRP0001") Name (_CID, "SC18IS602B") Name (_ADR, 0x28) // I2C address of SC18IS602B // Configure SPI bus properties using _DSD (Device Specific Data) Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () { "compatible", "nxp,sc18is602b" }, Package () { "spi-num-cs", 4 }, // Matches your 4 TPS92518HV-Q1 chips Package () { "clock-frequency", 1000000 }, // SPI clock rate (adjust as needed) } }) // Add downstream SPI devices (TPS92518HV-Q1) Device (SPI1) // First TPS92518HV-Q1 (CS0) { Name (_ADR, 0x00) // SPI chip select 0 Name (_HID, "PRP0001") Name (_CID, "TPS92518HV-Q1") Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () { "compatible", "ti,tps92518hv-q1" }, // Add device-specific properties (e.g., current limits) here if needed } }) } // Repeat for remaining TPS92518HV-Q1 chips (CS1-CS3) Device (SPI2) { Name (_ADR, 0x01) // CS1 Name (_HID, "PRP0001") Name (_CID, "TPS92518HV-Q1") // Same _DSD block as SPI1 } Device (SPI3) { /* CS2, same structure */ } Device (SPI4) { /* CS3, same structure */ } } }
4. Add SC16IS741A (I2C-to-UART) to PCA9543 Channel 0
Next, declare the SC16IS741A under channel 0, set its I2C address, and define the UART bus. Let's use address 0x48 (adjust based on your hardware's A0/A1/A2 pins):
Device (CH0) { Name (_ADR, 0x00) // ... existing SPIB device ... Device (UART) // SC16IS741A device node { Name (_HID, "PRP0001") Name (_CID, "SC16IS741A") Name (_ADR, 0x48) // I2C address of SC16IS741A // Configure UART properties Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () { "compatible", "nxp,sc16is741a" }, Package () { "current-speed", 115200 }, // Baud rate matching TPS92662-Q1 Package () { "reg-io-width", 1 }, // 1-byte register access } }) // Note: For TPS92662-Q1 (addressable RS-485 UART), you don't need to declare them in ACPI. // Their addressing is handled via software—once the SC16IS741A driver loads, communicate with each TPS92662 via their unique addresses in your userspace or kernel code. } }
5. Compile and Load the SSDT
Once your SSDT is written, follow these steps to deploy it:
- Install the ACPI compiler:
sudo apt install iasl - Compile your SSDT source (save as
custom-pcb.dsl) to a binary:iasl -tc custom-pcb.dsl - Copy the compiled
custom-pcb.amlto the ACPI boot directory:sudo mkdir -p /boot/acpi sudo cp custom-pcb.aml /boot/acpi/ - Edit your GRUB config to load the SSDT:
Addsudo nano /etc/default/grubacpi_osi=! acpi_osi="Windows 2009"toGRUB_CMDLINE_LINUX_DEFAULT(to ensure ACPI compatibility) and update the initrd line to include your SSDT, or useupdate-initramfsto embed it. - Update GRUB and initramfs:
sudo update-grub sudo update-initramfs -u - Reboot, then verify devices are detected with
i2cdetect -l,ls /dev/spi*, andls /dev/tty*.
Key Notes
- I2C Addresses: Double-check the A0/A1/A2 pin wiring on each chip to confirm their I2C addresses—these must match your hardware.
- Driver Compatibility: Ensure kernel modules for PCA9543 (
pca954x), SC18IS602B (sc18is602), SC16IS741A (sc16is7xx), and your downstream chips are available in Ubuntu 18.04's kernel. If not, compile them from source. - GPIO Interrupt Mode: Make sure your GPIO is configured for edge-triggered interrupts (you can set this via sysfs or extend the SSDT to handle it).
内容的提问来源于stack exchange,提问作者fireblade

