Linux 驱动总线中的 ACPI 设备匹配机制概述
在 Linux 内核中,ACPI(Advanced Configuration and Power Interface,高级配置与电源管理接口)提供了一种标准化的方法来描述硬件,并支持设备自动发现和电源管理。
在驱动总线(如 PCI、I2C、SPI、Platform 等)中,ACPI 匹配主要用于 在不依赖设备树(Device Tree)的情况下自动匹配设备和驱动。
一个具体的示例
下面是SPI总线驱动的一个实例:spidev.c,相关代码路径和截图如下:
\Linux-4.9.88\drivers\spi\spi.c
\Linux-4.9.88\drivers\spi\spidev.c
\Linux-4.9.88\drivers\spi\spidev.c
1. ACPI 匹配的基本原理
在 ACPI 系统中,每个设备由 ACPI 名称空间(ACPI Namespace) 描述,ACPI 表(如 DSDT)中包含 Device
结构,定义了该设备的 硬件 ID(HID)和 兼容 ID(CID)。
示例:ACPI DSDT 表中的设备定义
Device (I2C1)
{Name (_HID, "INTC1000") // 硬件 IDName (_CID, "INTC1001") // 兼容 ID(可选)Name (_UID, 1) // 唯一 IDName (_CRS, ResourceTemplate() {I2cSerialBus(0x50, ControllerInitiated, 400000,AddressingMode7Bit, "\\_SB.I2C1", 0x00, ResourceConsumer)})
}
_HID
(Hardware ID):用于设备驱动匹配,例如"INTC1000"
。_CID
(Compatible ID):用于向后兼容性匹配,例如"INTC1001"
。_CRS
(Current Resource Settings):描述 I2C 地址、SPI 片选、IRQ 号等资源信息。
当 Linux 内核启动时,它会解析 ACPI 表,并创建相应的设备节点。
2. Linux 内核中的 ACPI 匹配
在 Linux 设备驱动程序中,可以通过 acpi_match_table
进行 ACPI 设备匹配。
示例 1:Platform 设备 ACPI 匹配
static const struct acpi_device_id my_acpi_ids[] = {{ "INTC1000", 0 }, // 匹配 ACPI DSDT 表中的 _HID{ "INTC1001", 0 }, // 匹配 ACPI DSDT 表中的 _CID{ }
};
MODULE_DEVICE_TABLE(acpi, my_acpi_ids);static struct platform_driver my_platform_driver = {.driver = {.name = "my_platform_device",.acpi_match_table = ACPI_PTR(my_acpi_ids), // ACPI 设备匹配表},.probe = my_probe,.remove = my_remove,
};
my_acpi_ids[]
:定义了 ACPI 设备匹配表,包含HID
和CID
。MODULE_DEVICE_TABLE(acpi, my_acpi_ids);
:将匹配表导出到内核设备表,modinfo
可查看 ACPI 兼容 ID。acpi_match_table = ACPI_PTR(my_acpi_ids);
:告诉内核该驱动支持 ACPI 设备匹配。
示例 2:I2C 设备 ACPI 匹配
对于 I2C 设备:
static const struct acpi_device_id my_i2c_acpi_ids[] = {{ "INTC2000", 0 }, // ACPI DSDT _HID{ }
};
MODULE_DEVICE_TABLE(acpi, my_i2c_acpi_ids);static struct i2c_driver my_i2c_driver = {.driver = {.name = "my_i2c_device",.acpi_match_table = ACPI_PTR(my_i2c_acpi_ids),},.probe = my_i2c_probe,.remove = my_i2c_remove,
};
- 当 ACPI DSDT 中定义的
_HID
= “INTC2000”` 时,驱动会自动匹配这个 I2C 设备。
3. ACPI 设备匹配 vs. 设备树(Device Tree)
匹配方式 | ACPI | 设备树(DT) |
---|---|---|
主要用于 | x86、部分 ARM64 | ARM、RISC-V |
设备描述 | DSDT 表(BIOS/UEFI 提供) | .dts 文件 |
设备发现 | 固件自动发现 | 由内核解析设备树 |
匹配方式 | .acpi_match_table | .of_match_table |
资源分配 | _CRS 方法提供 | reg 、interrupts |
热插拔支持 | 良好(动态枚举) | 有限 |
- x86 设备(如笔记本、工控机)通常使用 ACPI 设备匹配。
- ARM 设备(如树莓派、嵌入式系统)主要使用设备树。
4. ACPI 设备调试
查看已识别的 ACPI 设备
ls /sys/bus/acpi/devices/
ls /sys/bus/acpi/devices/INTC1000/
查看 ACPI 设备的匹配驱动
ls /sys/bus/platform/devices/
查看 ACPI 设备信息
cat /sys/bus/acpi/devices/INTC1000/status
cat /sys/bus/acpi/devices/INTC1000/path
使用 dmesg
检查 ACPI 设备注册
dmesg | grep ACPI
5. MODULE_DEVICE_TABLE(acpi, ...)
的作用
在驱动程序中:
MODULE_DEVICE_TABLE(acpi, my_acpi_ids);
- 作用:将 ACPI 设备匹配表导出到 内核的设备表,供
modinfo
查询。 - 查看匹配信息:
可能会输出:modinfo my_driver.ko
alias: acpi*:INTC1000:* alias: acpi*:INTC1001:*
如果省略 MODULE_DEVICE_TABLE(acpi, my_acpi_ids);
,驱动仍能匹配 ACPI 设备,但 modinfo
不会显示匹配信息,可能会影响 自动模块加载。
总结
- ACPI 匹配用于 x86 设备(部分 ARM64 也支持),是设备自动发现的重要机制。
- 通过
_HID
和_CID
进行设备匹配,acpi_match_table
在驱动中用于 ACPI 设备匹配。 - 相比设备树,ACPI 设备匹配更适用于动态设备(如 PCI、USB、I2C、SPI)。
MODULE_DEVICE_TABLE(acpi, my_acpi_ids);
让modinfo
识别 ACPI 匹配信息,有助于自动加载驱动。