ACPI: Adding Devices Without Kernel Recompilation
As it turns out, far few are aware of the existence of an overlay mode in ACPICA and their support in Linux. I want to fill this gap with the example of adding I2C slaves to the system without recompiling.
Let's say at startup
we have the following picture:
where the ADXL345 accelerometer is detected at address 0x53, and the 24c128 memory EEPROM chip is located at address 0x57. Descriptions of these devices are not available in ACPI, namely in the DSDT table .
All we need to know here is the address at which the device responds, its IDs supported by the driver, the frequency of the bus on which it should work. Please note that the frequency of the I2C bus on the driver side is often set to the minimum that is supported by all slave devices on this bus!
Oh yes, there was a time when the IIO subsystem did not exist, and the ADXL345 driver already existed. So, we are using a new one that is available through the IIO subsystem.
Total
It should be noted that we use a special identifier here, which is intended for systems with OF . As a layer in ACPI, a special identifier PRP0001 was added , which ensures compatibility with drivers written earlier for OF.
We translate the received information into ASL :
As in the previous case, we obtain the necessary information about the device and its driver:
Notice the difference with the previous option. It uses the ACPI ID directly, which is allocated in the space controlled by Intel, thanks to the Intel Galileo platform. The second difference, we pass additional device parameters in the form of key-value strings.
What now to do with all this? The algorithm is simple. First, you need to compile the resulting files into ASL bytecode. Achieved by calling a command
and by analogy for EEPROM. Secondly, choose a way to initialize the newly made table. There are actually three of them: 1) joining initramfs, 2) loading on the working system via ConfigFS, 3) loading the table from the EFI variable. Consider the first two of them below.
We will not do anything with the initramfs archive itself , however, it is recommended that you save the original somewhere aside.
After this procedure, you can replace the old archive with a new one and restart the computer.
Something like this should appear in the dmesg output:
Note that the kernel only supports a chain of up to 64 such archives.
This feature is available when the kernel is compiled with the CONFIG_ACPI_CONFIGFS option and ConfigFS is mounted. Assuming it is mounted in the / sys / kernel / config subdirectory , the following example shows how to load a table.
Although ASL requires more brackets than analogs, it nevertheless provides no less opportunities to describe devices. So, there are a number of examples in the meta-acpi project , where in particular you can find descriptions of LEDs and buttons connected to GPIO lines, memory chips, and even a description of the Adafruit 2.8 " module - TFT display with a touch screen!
Initial conditions
Let's say at startup
i2cdetect -y -r 0
we have the following picture:
I2cdetect output
0 1 2 3 4 5 6 7 8 9 abcdef 00: - - - - - - - - - - - - - 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- thirty: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: - - - - - - - - - - - - - - - - - 50: - - - 53 - - - 57 - - - - - - - - 60: - - - - - - - - - - - - - - - - - 70: - - - - - - - -
where the ADXL345 accelerometer is detected at address 0x53, and the 24c128 memory EEPROM chip is located at address 0x57. Descriptions of these devices are not available in ACPI, namely in the DSDT table .
Add ADXL345 Accelerometer
All we need to know here is the address at which the device responds, its IDs supported by the driver, the frequency of the bus on which it should work. Please note that the frequency of the I2C bus on the driver side is often set to the minimum that is supported by all slave devices on this bus!
Oh yes, there was a time when the IIO subsystem did not exist, and the ADXL345 driver already existed. So, we are using a new one that is available through the IIO subsystem.
Total
- Address: 0x53
- Bus Frequency: 400kHz
- Link to master (controller) device: \ _SB.PCI0.I2C1
- ID: adi, adxl345
It should be noted that we use a special identifier here, which is intended for systems with OF . As a layer in ACPI, a special identifier PRP0001 was added , which ensures compatibility with drivers written earlier for OF.
We translate the received information into ASL :
ASL Code for ADXL345 Accelerometer
DefinitionBlock ("adxl345.aml", "SSDT", 5, "", "ADXL345", 1)
{
External (_SB_.PCI0.I2C1, DeviceObj)
Scope (\_SB.PCI0.I2C1)
{
Device (ACL0) {
Name (_HID, "PRP0001")
Name (_DDN, "Analog Devices ADXL345 3-axis accelerometer")
Name (_CRS, ResourceTemplate () {
I2cSerialBusV2 (
0x0053, // I2C Slave Address
ControllerInitiated,
400000, // Bus speed
AddressingMode7Bit,
"\\_SB.PCI0.I2C1", // Link to ACPI I2C host controller
0
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "compatible", "adi,adxl345" },
}
})
}
}
}
Add EEPROM 24c128
As in the previous case, we obtain the necessary information about the device and its driver:
- Address: 0x57
- Bus Frequency: 400kHz
- Link to master (controller) device: \ _SB.PCI0.I2C1
- ID number: INT3499
- Volume: 1024
- Page Size: 32
ASL code for EEPROM 24c128
DefinitionBlock ("at24.aml", "SSDT", 5, "", "AT24", 1)
{
External (_SB_.PCI0.I2C1, DeviceObj)
Scope (\_SB.PCI0.I2C1)
{
Device (EEP0) {
Name (_HID, "INT3499")
Name (_DDN, "Atmel AT24 compatible EEPROM")
Name (_CRS, ResourceTemplate () {
I2cSerialBusV2 (
0x0057, // I2C Slave Address
ControllerInitiated,
400000, // Bus speed
AddressingMode7Bit,
"\\_SB.PCI0.I2C1", // Link to ACPI I2C host controller
0
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "size", 1024 },
Package () { "pagesize", 32 },
}
})
}
}
}
Notice the difference with the previous option. It uses the ACPI ID directly, which is allocated in the space controlled by Intel, thanks to the Intel Galileo platform. The second difference, we pass additional device parameters in the form of key-value strings.
Possible initialization options
What now to do with all this? The algorithm is simple. First, you need to compile the resulting files into ASL bytecode. Achieved by calling a command
iasl adxl345.asl
and by analogy for EEPROM. Secondly, choose a way to initialize the newly made table. There are actually three of them: 1) joining initramfs, 2) loading on the working system via ConfigFS, 3) loading the table from the EFI variable. Consider the first two of them below.
Joining initramfs
We will not do anything with the initramfs archive itself , however, it is recommended that you save the original somewhere aside.
# Добавляем ACPI таблицы в некомпрессированный cpio архив.
# Они обязаны находится в подкаталоге /kernel/firmware/acpi внутри архива.
# Некомпрессированные архивы должны идти первыми в цепочке.
mkdir -p kernel/firmware/acpi
cp adxl345.aml kernel/firmware/acpi
cp at24.aml kernel/firmware/acpi
# Создаём архив и цепочкой к нему присоединяем оригинальный initramfs:
find kernel | cpio -H newc --create > /boot/instrumented_initramfs-vX.Y
cat /boot/initramfs-vX.Y >> /boot/instrumented_initramfs-vX.Y
After this procedure, you can replace the old archive with a new one and restart the computer.
Something like this should appear in the dmesg output:
[ 0.000000] ACPI: Table Upgrade: install [SSDT- - ADXL345]
[ 0.000000] ACPI: SSDT 0x000000003F4FF5C4 0000A6 (v05 ADXL345 00000001 INTL 20170303)
Note that the kernel only supports a chain of up to 64 such archives.
Download via ConfigFS
This feature is available when the kernel is compiled with the CONFIG_ACPI_CONFIGFS option and ConfigFS is mounted. Assuming it is mounted in the / sys / kernel / config subdirectory , the following example shows how to load a table.
cd /sys/kernel/config/acpi/table
mkdir adxl345
cat ~/adxl354.aml > adxl345/aml
Conclusion
Although ASL requires more brackets than analogs, it nevertheless provides no less opportunities to describe devices. So, there are a number of examples in the meta-acpi project , where in particular you can find descriptions of LEDs and buttons connected to GPIO lines, memory chips, and even a description of the Adafruit 2.8 " module - TFT display with a touch screen!