📜 ⬆️ ⬇️

ACPI: Adding devices without recompiling the kernel

As it turns out, few people know about the existence of overlay mode in ACPICA and their support in Linux OS. I want to fill this gap with the example of adding I2C slaves to the system without recompiling.

Initial conditions


Let's say at startup

i2cdetect -y -r 0 

we have this picture:

I2cdetect output
      0 1 2 3 4 5 6 7 8 9 abcdef
 00: - - - - - - - - - - - - - 
 ten: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
 thirty: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
 40: - - - - - - - - - - - - - - - - 
 50: - - - 53 - - - 57 - - - - - - - - 
 60: - - - - - - - - - - - - - - - - 
 70: - - - - - - - -                         


where at the address 0x53 the accelerometer ADXL345 is detected, and at address 0x57 - the 24c128 memory chip EEPROM. Descriptions of these devices are missing in ACPI, namely in the DSDT table.
')

Adding accelerometer ADXL345


All we need to know here is the address to which the device responds, its ID 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 was already there. So, we use a new one that is available through the IIO subsystem.

Total


It should be noted that we use here a special identifier that is intended for systems with OF . As a layer, a special identifier PRP0001 was added to ACPI, which ensures compatibility with the drivers written earlier for OF.

We translate this information into ASL :

ASL code for the accelerometer ADXL345
 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


Just as in the previous case, we obtain the necessary information about the device and its driver:


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 }, } }) } } } 


Note 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 is that we pass additional device parameters in the form of key-value strings.

Possible initialization options


What to do now with this? The algorithm is simple. First, you need to compile the resulting files in the ASL bytecode. Achieved by calling the command

 iasl adxl345.asl 

and by analogy for eeprom. Secondly, choose the method of initializing the new table. There are actually three of them: 1) joining the initramfs, 2) loading on the work 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 to keep 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.
It should appear in the dmesg output of something like:

 [ 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.

ConfigFS download

This feature is available when the kernel is built with the CONFIG_ACPI_CONFIGFS option and ConfigFS mounted. Assuming that it is mounted in the / sys / kernel / config subdirectory, the following example shows how to load the table.

 cd /sys/kernel/config/acpi/table mkdir adxl345 cat ~/adxl354.aml > adxl345/aml 

Conclusion


Although the ASL language requires more brackets than analogs, it nevertheless provides no less opportunity for describing 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 the description of the Adafruit 2.8 " module - TFT touch-screen display!

Source: https://habr.com/ru/post/451668/


All Articles