Issue receiving data on IMX8MM UARTs

We were able to hire some outside help to get this resolved. Our Yocto environment was set up to use the 5.4 kernel which does not have IMX8 device tree files. Those files were manually added into the build system by a different engineer who left the company in December 2021.

I believe the version of imx8mm-pinfunc.h we were using came from here: freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules

The mux register definitions for the SAI3_TXFS and SAI3_TXC pins (uart2 in the device tree, or verdin-uart1 in sysfs) in the 5.4-2.3 version have four UART options each:

#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX                                 0x1D8 0x440 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_TX                                 0x1D8 0x440 0x4FC 0x4 0x2
#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DTE_RX                                 0x1D8 0x440 0x4FC 0x4 0x2
#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DTE_TX                                 0x1D8 0x440 0x000 0x4 0x0
. . .
#define MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_RX                                  0x1DC 0x444 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX                                  0x1DC 0x444 0x4FC 0x4 0x3
#define MX8MM_IOMUXC_SAI3_TXC_UART2_DTE_RX                                  0x1DC 0x444 0x4FC 0x4 0x3
#define MX8MM_IOMUXC_SAI3_TXC_UART2_DTE_TX                                  0x1DC 0x444 0x000 0x4 0x0

but in the master kernel branch (linux/imx8mm-pinfunc.h at master · torvalds/linux · GitHub), only two options are present for each:

#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX                                 0x1D8 0x440 0x4FC 0x4 0x2
#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DTE_TX                                 0x1D8 0x440 0x000 0x4 0x0
. . .
#define MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX                                  0x1DC 0x444 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI3_TXC_UART2_DTE_RX                                  0x1DC 0x444 0x4FC 0x4 0x3

We believe that the final value was the culprit, which gives the daisy chain setting for RS-485. Also, because I was seeing strange behavior on both UARTs, I think I had been making the same changes to both (DCE → DTE and back). Given these incorrect pinfunc options, that meant that at least one of them would always be essentially nonfunctional.

Lessons Learned

  • Use up-to-date version of kernel files when possible, or at least generate a diff between your version and the current version to see if any important bugfixes should be made in your version.

  • Document device tree changes and results of the tests

  • Just because it’s a kernel file doesn’t mean it’s bug-free

Hopefully this can help someone in the future!