We are running an iMX7s processor with Linux on the A-core and MQX on the M-core. The M-core is booted first and sets up the GPIO it needs and begins running. The A-core finishes booting Linux at a later point in time and we have found that the GPIO driver associated with imx35-gpio (found in the imx7s.dtsi) is completely re-initializing all GPIO ports, 'stomping' on the settings the M-core/MQX had established.
The driver is gpio-mxc.c on the Linux side, and the probe function, static int mxc_gpio_probe(struct platform_device *pdev) is clearing the entire port's IMR register among other things. From our debug output it appears that probe is called for each port listed in the dtsi, essentially clearing all gpio port settings and then setting up the individual pins called out in the DTS. This behavior seems OK if the A-core is the only core in operation, but this is not acceptable with the M-core already up and running. It seems that the driver should read/modify/write the port registers based on which pins are actually called out in the systems' DTS. Having the A-core boot first, then launching the M-core may mitigate this, but having the M-core up first is one of the 'selling' points of this processor.
I have tried resetting the M4 core after Linux has completed booting; this allows MQX to re-initialize all its own GPIO and associated interrupts, but the failure still occurs. Linux is responding to the interrupts and clearing the masks. The interrupts we are trying to use on the M-core are GPIO1 0-7. Each has its own interrupt vector. I have also tried installing a 'dummy' ISR for the group GPIO 0-15 interrupt, thinking that Linux was possibly still responding to this and inadvertently clearing the IMR, but no luck. Even after the M-core reboots and MQX reloads, the ISRs only fire in Linux, presumably handled by the default handlers, as we are not installing any interrupts on GPIO1 on the Linux side. I'm beginning to suspect that it may be a priority issue between the A-cores GIC and the M-cores NVIC?
Are we missing something or is this expected behavior?
Regarding the interrupts, all the interrupts are routed to the either Cortex-A and Cortex-M, so each core must mask the interrupt to allow the IP to generate the interrupt or not, for example:
The interrupt controller for Cortex-A is the Global Interrupt Controller and if application must cause interrupt only on M side, then it should be masked at GIC to disable it to reach the A Core.
On the other hand, in case the interrupt is intended to Cortex-A, then the Cortex-M must mask the interrupt on the M interrupt controller, which is the Nested Vector Interrupt Controller (NVIC).
By masking the interrupts on GIC and NVIC, the application routes the interrupts to one core or other. If one interrupt goes to both cores, then the RDC must be used to correct control which core is allowed to use the resource that generated the interrupt.
The deeper information about GIC and NVIC are on CPU Technical Reference Manual provided by ARM, so in case you need detailed information about GIC or NVIC, please download the documentation directly from arm.com.
Thank you for the reply,
Are there any code examples for this available? This seems like a pretty standard use-case for the iMX7 (6 and 8 included) family of parts to not be addressed in the Linux port?
Was there ever any solution to this? I am running into a similar problem where the A7 (running Linux) is affecting the interrupts on the M4.
Is there code available to control the masks of the interrupts on the interrupt controllers to redirect to the appropriate core? Or another configuration that can be done via RDC control?
Thanks very much,