如何保证SPI总线的探测顺序?

如何保证SPI总线的探测顺序?

我有一个基于 iMX8 CPU 的嵌入式 Linux 系统。我正在升级 yocto 版本,从而升级内核版本。

我在两条 SPI 总线上有两个 SPI 设备。第二条总线上的设备有一个驱动程序创建/dev/spidevX.X node,另一个不创建/dev/* node.

我注意到 SPI 设备的地址在内核升级期间似乎不一致:在以前的 yocto 版本中Kernel 5.4.24,第二个硬件 SPI 总线上的我的设备显示为/dev/spidev1.0一致。

升级到内核 5.15.71 后,节点大多显示为/dev/spidev2.0,但我也看到过/dev/spidev1.0

我的谷歌结果表明 / dev/spidevX.Yv 意味着X = bus, Y = device/CS

如何确保某个硬件总线始终获得某个总线号?

答案1

spidev (drivers/spi/spidev.c) 创建 /dev/spidevB.C,其中 B 是总线号,C 是片选:

dev = device_create(spidev_class, &spi->dev, spidev->devt,
            spidev, "spidev%d.%d",
            spi->master->bus_num, spi->chip_select); 

考虑SPI内核如何drivers/spi/spi.c

int spi_register_controller(struct spi_controller *ctlr)

分配控制器总线号(代码如下所示),有多种方法可以遇到内核之间的不一致问题(尽管不太可能)。

比较两个内核版本之间 SoC 设备树中的 SPI 控制器,看看定义是否不一致并解决:

例如,缺少在一个版本中定义某些控制器。

如果不存在此类不一致,则检查设备树别名是否存在任何不一致并解决它(其中of_alias_get_idof_alias_get_highest_id在下面的代码中可以发挥作用):

只是一个想象的例子,

在 SoC 的 5.4.y 中

aliases {
    :
    spi0 = &ecspi1;
    spi1 = &ecspi2;
    spi2 = &ecspi3;
};

但在 SoC 5.15.y 中

aliases {
    :
    spi0 = &ecspi3;
    spi1 = &ecspi1;
    spi2 = &ecspi2;
};

如果您的设备树没有任何 SPI 别名,并且您遇到不一致的情况,请尝试在控制器的两个树中使用相同的编号添加 SPI 别名:

例如,

aliases {
    :
    spi0 = &lpspi1;
};

所以,这里我们使用数字0茎后SPI所以of_alias_get_id或者of_alias_get_highest_id可以选择那个。

我没有具体检查您提到的内核版本,并且您没有提到 iMX8 SoC(但通过查看 lf-5.4.y 和 lf-5.15.y 很可能是 iMX8QXP,因为我没有看到 SPI 控制器在 DT 中,因此您必须定义它们,因此可能会遇到不一致的情况,但我不确定)。

SPI 控制器总线编号分配来自drivers/spi/spi.c

int spi_register_controller(struct spi_controller *ctlr)
{

    if (ctlr->bus_num >= 0) {
        /* devices with a fixed bus num must check-in with the num */
        mutex_lock(&board_lock);
        id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
            ctlr->bus_num + 1, GFP_KERNEL);
        mutex_unlock(&board_lock);
        if (WARN(id < 0, "couldn't get idr"))
            return id == -ENOSPC ? -EBUSY : id;
        ctlr->bus_num = id;
    } else if (ctlr->dev.of_node) {
        /* allocate dynamic bus number using Linux idr */
        id = of_alias_get_id(ctlr->dev.of_node, "spi");
        if (id >= 0) {
            ctlr->bus_num = id;
            mutex_lock(&board_lock);
            id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
                       ctlr->bus_num + 1, GFP_KERNEL);
            mutex_unlock(&board_lock);
            if (WARN(id < 0, "couldn't get idr"))
                return id == -ENOSPC ? -EBUSY : id;
        }
    }
    if (ctlr->bus_num < 0) {
        first_dynamic = of_alias_get_highest_id("spi");
        if (first_dynamic < 0)
            first_dynamic = 0;
        else
            first_dynamic++;

        mutex_lock(&board_lock);
        id = idr_alloc(&spi_master_idr, ctlr, first_dynamic,
                   0, GFP_KERNEL);
        mutex_unlock(&board_lock);
        if (WARN(id < 0, "couldn't get idr"))
            return id;
        ctlr->bus_num = id;
    }

}

相关内容