ACPI:添加没有内核重新编译的设备

事实证明,很少有人知道ACPICA中是否存在覆盖模式以及Linux中对它们的支持。 我想用在不重新编译的情况下将I2C从站添加到系统的示例来填补这一空白。

初始条件


假设在启动时

i2cdetect -y -r 0 

我们有以下图片:

I2cdetect输出
      0 1 2 3 4 5 6 7 8 9 abcdef
 00:-------------- 
 10:------------------ 
 20:------------------ 
 30:------------------ 
 40:------------------ 
 50:---53---57--------- 
 60:------------------ 
 70:--------                         


其中在地址0x53处检测到ADXL345加速度计,而24c128存储器EEPROM芯片位于地址0x57处。 这些设备的描述在ACPI(即DSDT表)中不可用。

添加ADXL345加速度计


我们在这里只需要知道设备响应的地址,驱动程序支持的ID,应工作的总线频率即可。 请注意,驱动器侧I2C总线的频率通常设置为该总线上所有从设备支持的最低频率!

哦,是的,有一段时间IIO子系统不存在,并且ADXL345驱动程序已经存在。 因此,我们正在使用一个可通过IIO子系统使用的新工具

合计

  • 地址:0x53
  • 总线频率:400kHz
  • 链接到主(控制器)设备:\ _SB.PCI0.I2C1
  • ID:adi,adxl345

应该注意的是,我们使用一个特殊的标识符,该标识符旨在用于OF的系统。 作为ACPI中的一层,添加了特殊标识符PRP0001 ,以确保与先前为OF编写的驱动程序兼容。

我们将收到的信息转换为ASL

适用于ADXL345加速度计的ASL代码
 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" }, } }) } } } 


添加EEPROM 24c128


与前面的情况一样,我们获得有关设备及其驱动程序的必要信息:

  • 地址:0x57
  • 总线频率:400kHz
  • 链接到主(控制器)设备:\ _SB.PCI0.I2C1
  • 身份证号码:INT3499
  • 音量:1024
  • 页面大小:32

EEPROM 24c128的ASL代码
 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 }, } }) } } } 


注意与上一个选项的区别。 由于使用了Intel Galileo平台,它直接使用了ACPI ID,该ID在Intel控制的空间中分配。 第二个区别是,我们以键值字符串的形式传递其他设备参数。

可能的初始化选项


现在如何处理所有这些? 该算法很简单。 首先,您需要将生成的文件编译为ASL字节码。 通过调用命令实现

 iasl adxl345.asl 

并以EEPROM为例。 其次,选择一种方法来初始化新创建的表。 实际上有三个:1)加入initramfs,2)通过ConfigFS在工作系统上加载,3)从EFI变量加载表。 考虑下面的前两个。

加入initramfs

我们不会对initramfs归档文件本身做任何事情,但是,建议您将原始文件保存在旁边。

 #  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 

完成此步骤后,您可以将旧的存档替换为新的存档,然后重新启动计算机。
这样的事情应该出现在dmesg输出中:

 [ 0.000000] ACPI: Table Upgrade: install [SSDT- - ADXL345] [ 0.000000] ACPI: SSDT 0x000000003F4FF5C4 0000A6 (v05 ADXL345 00000001 INTL 20170303) 

请注意,内核仅支持多达64个此类档案的链。

通过ConfigFS下载

当使用CONFIG_ACPI_CONFIGFS选项编译内核并挂载ConfigFS时,此功能可用。 假定它已安装在/ sys / kernel / config子目录中,以下示例说明如何加载表。

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

结论


尽管ASL比类似物需要更多的括号,但是它提供了更多描述设备的机会。 因此,在meta-acpi项目中有许多示例,特别是在其中,您可以找到有关连接到GPIO线,存储芯片的LED和按钮的描述,甚至是Adafruit 2.8“模块的描述-带触摸屏的TFT显示屏!

Source: https://habr.com/ru/post/zh-CN451668/


All Articles