![i.MX28 SOC DMA 读取 NAND 闪存超时](https://linux22.com/image/154282/i.MX28%20SOC%20DMA%20%E8%AF%BB%E5%8F%96%20NAND%20%E9%97%AA%E5%AD%98%E8%B6%85%E6%97%B6.png)
我正在将最新的 Linux 内核移植到较旧的现有硬件,例如 Freescale 的 i.MX28 EVK 套件和 Karo TX28 板。我想使用NAND FLASH中文件系统的一部分(NAND中的“userfs分区”)。
第一步是使用 ubiattach /dev/ubi_ctrl -m 6。此操作尝试查找卷表,并读取 NAND 芯片,进行一些 gpmi_read_page 操作。这会导致 start_dma_without_bch_irq (gpmi-nand.c) 中的 DMA 超时。奇怪的是,第一个 read_page 操作成功了。然后暂停。
第一印象是时间问题。改变 NAND 时序并没有改变观察到的行为。大量调试,主要集中在 GPMI、GPIO 和中断收集器寄存器中的值,没有透露任何信息。
我设法在 i.MX28 EVK 板中的 NAND 芯片的控制线上建立了一些测量连接。使用 Saleae(仿)逻辑分析仪,我可以看到许多正确的事务(在 20、40 等范围内)。然后设置读取,NAND 信号准备好正确,要求 GPMI 读取数据,并且 GPMI 确实将数据从 NAND 中输出,但是失败设置芯片使能线(低电平有效)。看起来 GPMI 内部不再正常工作。现在,用于发出读操作结束信号的 ISR 尚未输入(我使用第二个芯片使能线来发出信号,调试输出讲述了相同的故事)。因此超时。看来GPMI内部“混乱”了。
我确实检查了芯片使能线的引脚多路复用器在超时后仍然正确。判断调试输出时,Karo TX 28 上也会发生同样的情况(引脚上没有测量,我无法连接)。
我见过与 i.MX23 问题相关的旧邮件,并重置 GPMI 两次(U-boot 和 Linux 内核),导致 GPMI 挂起。使用该修复程序并没有改变。在 Linux 内核 5.0.8 和 4.20.7 上观察到此问题。据我判断,从 U-Boot 使用时 NAND 工作正常。我尝试了与 U-Boot 使用的相同的计时设置,但没有成功。
另请注意,Karo 板上使用了三星 NAND,i.MX28 EVK 上使用了 Spansion 的部件。所以这似乎与特定的NAND芯片无关。另请注意,当从 U-boot 中的 Linux 引导命令行附加 NAND 分区时,也会观察到相同的情况。
问题是如何找到根本原因以及可能的解决方案。
答案1
首先我进行了大量的调试,没有找到解决方案。然后我意识到我在旧的 Linux 版本上可以工作(它是由另一家公司在几年前准备的)。这证明不是硬件问题。此外,两个不同的硬件板显示相同的问题这一事实表明不是硬件问题。在某个时候,我决定尝试旧的 Linux 版本,尽可能接近旧的工作解决方案。这表明内核 3.16.68 使用自己的构建工作正常。我的 5.1.5 和 4.20.7 版本显示了 NAND 闪存问题。更多实验表明,最后一个工作内核是 4.16.18,从 4.17.1 及更高版本开始出现该问题。看来,飞思卡尔 GPMI 外设的 NAND FLASH 支持已经被重组。我认为这是由飞思卡尔完成的,以适应更新的处理器/SOC。看来对旧硬件的支持已被破坏。我不知道飞思卡尔是否知道这一点。有迹象表明飞思卡尔不再支持旧的 i.MX28。无论如何,现在是时候分析差异了。关键的区别在于添加的用于调整 GPMI 外设时钟频率的函数调用。无论出于何种原因,在注释掉这一单一调用后,GPMI 外设似乎可以与 NAND 闪存一起正常工作。该代码位于文件“drivers/mtd/nand/raw/gpminand/gpmi-lib.c”中,函数“gpmi_nfc_apply_timings”。只需注释掉对“clk_set_rate”的调用即可。至少对我来说这有效。后来我意识到,最好只在处理器是 i.MX28 时避免调用,以允许它为以后的芯片工作。
我没有分析 clk_set_rate 到底做了什么,以及如何调用它来为所有处理器工作。我没有其他硬件,所以无法检查。