概要
FRDM-IMX93ボードの P11 EXPIヘッダーに LPSPI3 を使って、2つの外部MCP2515 CANコントローラー(Waveshare 2-CHAN HAT、本物のRaspberry Piで動作確認)を起動しようとしています(GPIO_IO08 UM12181表21参照、Raspberry-Pi互換ヘッダー位置に一致するピンです)。
見つけたデバイスツリーレベルの問題(電源、ピンマックス、チップセレクト、pinctrl-assert-gpio)をすべて修正した後、SPIクロック(SCK)は物理ヘッダーピンを切り替え ず 、LPSPI3ブロックの直接レジスタ読み込みは バスエラーを引き起こします。別の既知の動作ペリフェラル(LPUART1)は同じアドレス空間から問題なく読み返します。これはLinuxデバイスツリーから修正できるものではなく、リソース/バスアクセス制限(RDCなど)を示しています。
ボード/ソフトウェア
- ボード:FRDM-IMX93(NXP)、SoC:MIMX9352CVVXMAB
- BSP: NXP i.MX リリース ディストリビューション、カーネル 6.18.2-1.0.0-gf49f45233f7b
- ターゲット周辺機器:lpspi3(spi@42550000、/aliasesでエイリアスされたspi2、/proc/device-tree/で確認された本物のdtsラベル__symbols__ lpspi3)
- テスト中の外部デバイス:CS0/CS1上の2× MCP2515(Waveshare 2-CH CAN HAT)
既に動作が確認されているもの(除外されたもの)
- ヘッダーに電力を供給します。reg_vexp_3v3 / reg_vexp_5v は、デフォルトで無効になっているレギュレータ固定ノードです (regulator_summary では use=0 と表示されています)。レギュレーター常時オン+レギュレーターブートオンを追加し、オーバーレイフラグメントのターゲティング®_vexp_3v3/®_vexp_5vを追加しました( __symbols__で実際のラベルが確認されました)。その後、P11に3.3V/5Vの電圧が物理的に存在していることを確認しました。
- Pinmux。GPIO_IO08-11 は、imx93-pinfunc.h の公式マクロを使用して、LPSPI3_PCS0/SIN/SOUT/SCK に正しく多重化されています。input_reg/input_valはこれら3つの機能に対して0x0000/0x0であるため、DAISYチェーンセレクトは不要です(マクロ検査で除外され、個別レジスタは不要)。
- チップセレクト。cs-gpios = 、(ビットバンギングされたGPIO CS。このノードに対するNXP独自のアップストリームボードサポートパターンに一致)。cat /sys/kernel/debug/gpio とマルチメーター/ロジックアナライザーで確認したところ、 CS0 は正しくトグルし、物理的にヘッダーピンに到達していることがわかりました。
- pinctrl-assert-gpios。NXP独自のこのボード用アップストリーム&lpspi3リファレンスには、pinctrl-assert-gpios = <&pcal6408 0 GPIO_ACTIVE_HIGH>; が含まれています(この行はほとんどの公開ガイドには記載されておらず、ボード独自のdtsパッチにのみ記載されています)。追加しました。/proc/device-tree/__symbols__ で pcal6408 が解決されること、および cat /sys/kernel/debug/gpio で lpspi3 のデフォルトの pinctrl 状態が要求されると GPIO がアサートされる (出力 hi) ことを確認しました。
- オーバーレイはきれいに適用されます。U-Bootのfdt applyからFDT_ERR_NOTFOUNDは発生せず、/sys/bus/spi/devices/にはSPIコアによってspi2.0とspi2.1が登録されていることが示されています。
- ERR051608 (LPSPI TCR[PRESCALE] のエラータ)。spi-fsl-lpspi.c を確認しました履歴 — 修正(fsl、imx93-spi の prescale_max = 1)は、2024年8月 / 安定版 6.6.51 でメインラインに取り込まれました。2024年9月6.10日は、このカーネルバージョン(6.18.2)よりずっと前のもので、互換文字列(fsl、imx93-spi)はすでにベースボードのdtsに存在しているため、ドライバはこの制限を自動的に適用すべきです。完全に否定できるわけではないが(実際にPRESCALEフィールドが書き込まれたという直接的なレジスタ確認はない)、タイムラインから判断すると既に処理済みである可能性が高い。
実際の症状
CS0/CS1、MISO、MOSI、SCKが物理的なP11ピン(マルチメーター、CS0落ち込みエッジで10〜20 MSa/sのロジックアナライザーをトリガー)でプローブしつつ、転送を繰り返し再試行(ループ内でspidev_testし、Echo spi2.0 > /sys/bus/spi/drivers/mcp251x/bindを経て繰り返しMCP251xの再プローブを強制することで別々に実行しました):
- CS0の切り替え。マルチメーターとロジックアナライザーの両方で確認済み。
- SCKは切り替えません。継続的に転送を試みても、変化はなく、活動は見られない。
- MOSIは切り替えません。
- 両方のMCP2515が同じように失敗します:mcp251x spi2.0/spi2.1:リセット/プローブ失敗後、MCP251xはコンフモードに入らなかった。err=110(ETIMEDOUT)。つまり、ドライバ自身のSPIレベルのリセット+read-CANSTATシーケンスは応答せず、SCKがSoCを出ないのと一致している。
根本原因はデバイスツリーではなくクロック/バスアクセスに絞られます
# clk_enable_count is 0 despite the controller actively being used
$ cat /sys/kernel/debug/clk/clk_summary | grep -i lpspi3
lpspi3_root 0 0 0 50000000 0 0 50000 N deviceless no_connection_id
lpspi3 0 0 0 50000000 0 0 50000 N 42550000.spi perLPSpi3の機能クロック(per)クロックはenable_count=0と表示されますが、42550000.SPI(実際のバインドされた消費者)がループ内で転送を試みている間も、単に「未使用」ではありません(lpspi1/2/4はデバイス レスで0 と表示されるため、それだけでは決定的ではありません)。
決定的なテスト ― devmem を介したレジスタの直接読み取り:
$ devmem 0x44380000 32 # LPUART1 base — known-good peripheral
0x04040007
$ devmem 0x42550000 32 # LPSPI3 base (VERID register)
Bus error (core dumped)
全く関係のない動作するペリフェラル(LPUART1、デバッグコンソール用)は同じCPU/バスのコンテキストから問題なく読み戻せます。LPSPI3のベースアドレスフォルトは、クロックゲーティングやピンマックスの考慮が問題になる前に、単純な32ビット読み取りで発生します。これはリソースドメインコントローラー(RDC)やそれに類するアクセス制御機構が、ハードウェアレベルでCortex-A55(Linux)ドメインをこのペリフェラルのアドレス範囲からブロックしているように見えます。Linuxデバイスツリーから設定可能なものとは無関係です。
NXPへの質問
- FRDM-IMX93 の LPSPI3 は、別のドメイン (例:Cortex-M33 / Secure World)をボードのデフォルトのRDC構成に含めて、追加のSPL/ATF/TF-Aレベルの再構成なしでLinuxからは使えなくなるのでしょうか?
- もしそうなら、LPSPI3バスアクセスをCortex-A55の非セキュアドメインに再割り当てする方法(U-Boot SPLのRDC設定やOP-TEE/TF-Aの変更)は文書で記載されているのでしょうか?それとも、GPIO_IO08-11が壊れているにもかかわらず、このボードのP11ヘッダーで外部SPIとしては単純にサポートされていないのでしょうか?
- これは私のボード/カーネルビルド特有の問題でしょうか、それともデフォルトのFRDM-IMX93 BSPの既知の特性でしょうか?参照用のimx93-11x11-frdm-lpspi.dts(EVKの場合はimx93-11x11-evk-lpspi.dtsに相当)があれば非常に助かります。
再現方法
- ベースボードdtb: i.MXリリースディストリビューションイメージに同梱されている標準のimx93-11x11-frdm.dtb(変更されていないNXP lpspi3 + pcal6408 + reg_vexp_3v3/reg_vexp_5vノード - すべて__symbols__経由で存在が確認されています)。
- 上記で説明したオーバーレイを適用します(レギュレータ常時オン、&lpspi3 上の pinctrl + cs-gpios + pinctrl-assert-gpios)。
- spidev(組み込み、CONFIG_SPI_SPIDEV=y)を手動でspi2.0にバインドします。
echo spidev > /sys/bus/spi/devices/spi2.0/driver_override
echo spi2.0 > /sys/bus/spi/drivers/spidev/bind
- spidev_test -D /dev/spidev2.0-s 1000000 -v — 転送は「成功」します(I/O エラーなし)が、MOSI/MISO が物理的に短絡されていても、RX データは TX のループバックではありません。
- devmem 0x42550000 32 → バスエラー。
必要であれば、オーバーレイのソースコード、dmesgログ、clk_summary/gpioダンプなど、すべての情報を提供いたします。