用户通用驱动spidev.c与设备匹配问题
发现了一个奇怪的现象:
- 匹配成功了 :驱动确实跑起来了,
probe函数被调用了。 - 代码却说不匹配 :
spidev_dt_ids里明明没有"spidev",而且probe函数里还打印了"Buggy DT"警告。
设备树定义:
shell
&ecspi1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1>;
fsl,spi-num-chipselects = <2>;
cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>, <&gpio4 24 GPIO_ACTIVE_LOW>;
status = "okay";
dac: dac {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <2000000>;
};
};
spi_driver定义:
c
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
.of_match_table = of_match_ptr(spidev_dt_ids),
.acpi_match_table = ACPI_PTR(spidev_acpi_ids),
},
.probe = spidev_probe,
.remove = spidev_remove,
};
转入of_match_table的设备列表:
c
static const struct of_device_id spidev_dt_ids = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
发现spidev_dt_ids中并没有定义{ .compatible = "spidev" },,但最后还是能匹配成功。
-
先去看spi总线类型结构体:
cstruct bus_type spi_bus_type = { .name = "spi", .dev_groups = spi_dev_groups, .match = spi_match_device, .uevent = spi_uevent, }; -
找到match函数
spi_match_device:cstatic int spi_match_device(struct device *dev, struct device_driver *drv) { const struct spi_device *spi = to_spi_device(dev); const struct spi_driver *sdrv = to_spi_driver(drv); /* Attempt an OF style match */ if (of_driver_match_device(dev, drv)) return 1; /* Then try ACPI */ if (acpi_driver_match_device(dev, drv)) return 1; if (sdrv->id_table) return !!spi_match_id(sdrv->id_table, spi); return strcmp(spi->modalias, drv->name) == 0; }- 第 1 关:OF (设备树) 匹配
- 代码:
of_driver_match_device(dev, drv) - 动作:内核拿着你的
compatible = "spidev"去spidev_dt_ids列表里找。 - 结果:失败 。列表里只有
"rohm,dh2228fv"和"lineartechnology,ltc2488"。
- 代码:
- 第 2 关:ACPI 匹配
- 动作:x86 架构用的。
- 结果:失败。
- 第 3 关:ID Table 匹配
- 动作:检查传统 ID 表。
- 结果:失败。
- 第 4 关:名称 (Name) 匹配(在这里匹配成功)
- 代码:
return strcmp(spi->modalias, drv->name) == 0; - 核心逻辑 :
- 驱动名字
drv->name是"spidev"。 - 内核 SPI 核心层在解析设备树时,发现
compatible = "spidev",会将其设为该设备的modalias。 strcmp("spidev", "spidev")相等。
- 驱动名字
- 结果:匹配成功
- 代码:
- 第 1 关:OF (设备树) 匹配
-
为什么能匹配?
靠的是 spi_match_device 最后的字符串名称硬匹配机制(Fallback)。
-
为什么有警告?
[root@100ask:~]# dmesg | grep "DT" [ 2146.942455] spidev spi0.0: buggy DT: spidev listed directly in DTspidev_probe做了检查:
cif (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) { dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n"); WARN_ON(spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)); }