SPIバスの検出順序を保証する方法は?

SPIバスの検出順序を保証する方法は?

iMX8 CPUベースの組み込みLinuxシステムがあります。私はyoctoバージョンとカーネルバージョンをアップグレードしています。

2 つの SPI バスに 2 つの SPI デバイスがあります。 2番目のバス上のデバイスはあるドライバによって生成され、/dev/spidevX.X node別のドライバによって生成されません/dev/* node

カーネルのアップグレード中にSPIデバイスのアドレスが一致しないようです。以前の yocto バージョンでは、Kernel 5.4.242 番目のハードウェア SPI バス上のデバイスが/dev/spidev1.0一致することがわかりました。

カーネル5.15.71にアップグレードした後、ノードはほとんどとしてマークされますが/dev/spidev2.0、私も見たことがあります/dev/spidev1.0

私のGoogleの結果によると、/ 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)

コントローラバス番号(下記のコード)を割り当てると、コア間の不一致の問題が発生する可能性があります(可能性は低いですが)。

2つのカーネルバージョン間の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エイリアスがなく、不一致が発生した場合は、コントローラの2つのツリーに同じ番号の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を見るとSPIが表示されないので、iMX8QXPである可能性が最も高い)ので、これを定義する必要があるため、不一致が発生する可能性がありますが、わかりません。)

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;
    }

}

関連情報