I'm working on an embedded device based on an NXP i.MX8M mini SoC. It is running Linux based on NXP's "hardknott" Yocto recipe: https://source.codeaurora.org/external/imx/imx-manifest/tree/imx-5.10.52-2.1.0.xml?h=imx-linux-hardknott
Here's the bitbake script for the kernel it is using: https://source.codeaurora.org/external/imx/meta-imx/tree/meta-bsp/recipes-kernel/linux?h=hardknott-5.10.52-2.1.0
I believe it is pulling the kernel sources from here: https://source.codeaurora.org/external/imx/linux-imx/tree/?h=lf-5.10.y
Our device has a digital microphone that is being driven by a modified version of NXP's fsl_micfil.c
driver: https://source.codeaurora.org/external/imx/linux-imx/tree/sound/soc/fsl/fsl_micfil.c?h=lf-5.10.y
Our modifications are:
In
fsl_micfil_hw_params
, where their code does "enable channels" (around line 1592), we've changed it to only enable the channel we care about instead of all of them.We changed:
ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1, 0xFF, ((1 << channels) - 1));
To:
ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1, 0xFF, 1 << 6);
At the start of
fsl_micfil_probe
(around line 2202), we add code to pull a GPIO line (the mic's enable line) low. If GPIO isn't available at the time, we return-EPROBE_DEFER
in order to try again laterFurther down in
fsl_micfil_probe
(around line 2334), we change the DMA channel from 0 to 6 (to align with our enable change).We changed:
micfil->dma_params_rx.addr = res->start + REG_MICFIL_DATACH0;
To:
micfil->dma_params_rx.addr = res->start + REG_MICFIL_DATACH6;
That having been described, here's the problem.
Our application is trying to read audio from this microphone (we can test it with the arecord
command).
We have found that if we launch our application immediately after Linux boots, the device hangs. We need to power-cycle it to recover.
If we wait about 60 seconds after bootup, however, we see the following messages appear on the console:
[ 60.386133] imx-sdma 302c0000.dma-controller: firmware found.
[ 60.392010] imx-sdma 302c0000.dma-controller: loaded firmware 4.6
If we launch our application after these messages appear, everything works fine.
I looked through the implementation of the imx-sdma
driver: https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/dma/imx-sdma.c?h=lf-5.10.y
The driver loads some kind of firmware when it starts up. The first message ("firmware found") is presented by the probe function. The second ("loaded firmware") is presented by one of the two power management resume functions (sdma_resume
or sdma_runtime_resume
).
So it appears that the problem is that this DMA driver is not loading until the system has been running for about 60 seconds. I assume this is due to some kind of lazy initialization that waits until some kernel driver requires access. And my problem is happening because my driver requires access and is initializing before the DMA driver has loaded.
So, what's a good fix for this? I assume I need to add something to the fsl_micfil
driver to request startup of the DMA driver. But I don't know how to do this and I don't actually know if that is the correct fix for this problem.
What would you suggest as a proper fix for this bug?
(FWIW, we made very similar changes to an older version of the kernel - based on Yocto's "sumo" branch, running kernel 4.14, and there are no problems there. So clearly something changed between kernel 4.14 and 5.10 that our code needs to deal with, but I don't know what that might be.)