用户通用驱动spidev.c与设备匹配问题

用户通用驱动spidev.c与设备匹配问题

发现了一个奇怪的现象:

  1. 匹配成功了 :驱动确实跑起来了,probe 函数被调用了。
  2. 代码却说不匹配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" },,但最后还是能匹配成功。

  1. 先去看spi总线类型结构体:

    c 复制代码
    struct bus_type spi_bus_type = {
    	.name		= "spi",
    	.dev_groups	= spi_dev_groups,
    	.match		= spi_match_device,
    	.uevent		= spi_uevent,
    };
  2. 找到match函数spi_match_device

    c 复制代码
    static 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;
      • 核心逻辑
        1. 驱动名字 drv->name"spidev"
        2. 内核 SPI 核心层在解析设备树时,发现 compatible = "spidev",会将其设为该设备的 modalias
        3. strcmp("spidev", "spidev") 相等。
      • 结果:匹配成功
  • 为什么能匹配?

    靠的是 spi_match_device 最后的字符串名称硬匹配机制(Fallback)。

  • 为什么有警告?

    复制代码
    [root@100ask:~]# dmesg | grep "DT"
    [ 2146.942455] spidev spi0.0: buggy DT: spidev listed directly in DT

    spidev_probe做了检查:

    c 复制代码
    	if (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));
    	}
相关推荐
芯片设计-曾工6 小时前
当精准脉冲遇上清晰视界——CH2205E模块与YL1621的“黄金搭档“
驱动开发·stm32·单片机·51单片机·硬件工程
圆奋奋11 小时前
FreeRTOS学习(三)- 任务调度模块
学习·开源·freertos
LCG元11 小时前
STM32 硬件 SPI + DMA 驱动 OLED 显示屏(SSD1306):从原理到 112fps 高速刷新全流程
stm32·单片机·嵌入式硬件
210Brian13 小时前
STM32学习笔记(五)EXTI外部中断(上)
笔记·stm32·学习
崇山峻岭之间13 小时前
STM32F407的FOC驱动01
stm32·单片机·嵌入式硬件
Lzh编程小栈18 小时前
【嵌入式硬核精讲】I2C通信协议万字详解(时序帧格式、同步半双工、重复起始、一对多挂载、寄存器、面试必考)
stm32·单片机·嵌入式硬件·面试
十月的皮皮19 小时前
STM32从零到量产开发:四路继电器工业控制模块开发 -上位机 Program.cs 应用程序入口设计说明
c语言·stm32·单片机·stm32cubemx·hal库
LCG元19 小时前
STM32F103+MPU6050互补滤波姿态解算与OLED实时显示实战(附完整工程代码)
stm32·单片机·嵌入式硬件
小帽子_12320 小时前
STM32+BMS 嵌入式开发:ADC 电压温度采集与总线通信落地教程
stm32·单片机·嵌入式硬件
Lumos6fly1 天前
《嵌入式通讯协议栈实战》 5 AT24C02与OLED
stm32·单片机