摘要
我正在尝试在 FRDM-IMX93 板的P11 EXPI 接头上使用LPSPI3在 GPIO_IO08-11 上启动两个外部 MCP2515 CAN 控制器(Waveshare 2-CH CAN HAT,已确认在真正的 Raspberry Pi 上工作)(引脚与 UM12181 表 21 中 Raspberry Pi 兼容接头的位置相匹配)。
在修复了我能找到的所有设备树级问题(电源、引脚复用、片选、引脚控制断言-GPIO)之后,SPI 时钟 (SCK)始终无法在物理接头引脚上切换,并且直接读取 LPSPI3 块的寄存器会导致总线错误。另一个已知工作正常的外部设备(LPUART1)可以从相同的地址空间正常读取数据。这表明存在资源/总线访问限制(RDC 或类似限制),而不是 Linux 设备树中可以修复的问题。
板/软件
- 开发板:FRDM-IMX93(恩智浦),SoC:MIMX9352CVVXMAB
- BSP:NXP i.MX 发布发行版,内核版本 6.18.2-1.0.0-gf49f45233f7b
- 目标外设:lpspi3(spi@42550000,别名在 /aliases 中为 spi2,通过 /proc/device-tree/__symbols__ 确认实际 dts 标签为 lpspi3)
- 被测外部设备:CS0/CS1 上的 2 个 MCP2515(Waveshare 2 通道 CAN HAT)
已确认有效(已排除)
- 给排气歧管供电。reg_vexp_3v3 / reg_vexp_5v 是默认禁用的调节器固定节点(regulator_summary 显示 use=0)。通过覆盖片段添加了 regulator-always-on + regulator-boot-on,目标为 ®_vexp_3v3 / ®_vexp_5v(通过 __symbols__ 确认了真实标签)。事后验证 P11 上实际存在 3.3 V / 5 V 电压。
- Pinmux。使用 imx93-pinfunc.h 中的官方宏,GPIO_IO08‑11 已正确复用到 LPSPI3_PCS0/SIN/SOUT/SCK。对于这三个函数,input_reg/input_val 均为 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。& 6.10.10 2024 年 9 月,远早于此内核版本 (6.18.2),并且兼容字符串 (fsl,imx93-spi) 已存在于主板 dts 中,因此驱动程序应该自动应用此限制。虽然不能完全排除这种可能性(没有直接的注册确认实际写入了 PRESCALE 字段),但时间线强烈表明此事已经处理完毕。
实际症状
使用万用表探测物理 P11 引脚上的 CS0/CS1、MISO、MOSI、SCK,然后使用逻辑分析仪以 10–20 MSa/s 的采样率在 CS0 下降沿触发,同时不断重试传输(在循环中使用 spidev_test,以及通过 echo spi2.0 > /sys/bus/spi/drivers/mcp251x/bind 反复强制 mcp251x 重新探测):
- CS0切换。经万用表和逻辑分析仪验证。
- SCK 从不切换。平坦,无任何活动,无论持续尝试转移。
- MOSI 从不切换。
- 两个 MCP2515 的故障情况完全相同:mcp251x spi2.0/spi2.1:MCP251x 在复位后未进入配置模式 / 探测失败,错误代码为 110 (ETIMEDOUT) — 即驱动程序自身的 SPI 级复位 + 读取 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 per即使 42550000.spi(真正的、绑定的消费者)正在循环中积极尝试传输,lpspi3 的功能(每个)时钟也显示 enable_count=0——它并非只是“未使用”(与 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 设备树中的任何可配置项无关。
向恩智浦提出的问题
- FRDM-IMX93 上的 LPSPI3 是否故意保留给另一个功能域(例如,该板默认的 RDC 配置中包含 Cortex-M33 / secure world 内核,导致在 Linux 系统下,如果不进行额外的 SPL/ATF/TF-A 级重新配置,则无法使用该内核?
- 如果是这样,是否有记录在案的方法将 LPSPI3 总线访问权限重新分配给 Cortex-A55 非安全域(U-Boot SPL 中的 RDC 配置,或 OP-TEE/TF-A 更改),或者尽管 GPIO_IO08-11 已引出,但此板的 P11 接头上根本不支持外部 SPI?
- 这是我的板/内核版本特有的问题,还是默认 FRDM-IMX93 电路板支持包的已知特性?如果存在参考文件 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__ 确认存在)。
- 应用上述覆盖层(regulator always‑on, pinctrl + cs‑gpios + pinctrl‑assert‑gpios on &lpspi3)。
- 手动将 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 → 总线错误。
如果需要,我很乐意提供完整的 overlay 源代码、dmesg 和 clk_summary/gpio 转储。