IMX8M PLUS: GPIO Interrupt conflicts between M7 and A53

Hello,

Application: We want to use GPIOs with rising & falling edge interrupt on M7.

Problem:

It works when we halt uboot and run M7 binary. But when we boot with linux, Linux kernel panics.

So, we have disable unused and conflicting GPIOs from Device Tree. But the problem still occures. (Note: We cannot block whole “&gpio” node in device tree, as other hardware peripherals are using some gpio pins. some with interrupt and some without interrupt.)

Then we have used RDC with RDC_SEMA42 to temporary lock GPIO Port access on Linux.

Now, what happens is that, when interrupt gets from specific pins, M7 and A53 both calls IRQ. As a result, Linux kernel panics beacause we have blocked GPIO Port access from RDC. Linux Terminal Output is as follows:

[   37.410397] Internal error: synchronous external abort: 96000210 [#1] PREEMPT SMP
[   37.417885] Modules linked in: usb_f_rndis u_ether bluetooth ecdh_generic ecc rfkill crct10dif_ce snd_soc_imx_cdnhdmi snd_soc_hdmi_codec imx_sdma lm75 libcomposite configfs galcore(O)
[   37.434250] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G           O      5.4.193-5.7.2-devel+git.b60d3160fd04 #1
[   37.444159] Hardware name: Toradex Verdin iMX8M Plus WB on Verdin Development Board (DT)
[   37.452247] pstate: a0000085 (NzCv daIf -PAN -UAO)
[   37.457043] pc : mx3_gpio_irq_handler+0x3c/0xe8
[   37.461574] lr : generic_handle_irq+0x24/0x38
[   37.465926] sp : ffff800010003f60
[   37.469237] x29: ffff800010003f60 x28: ffff8000117f2080
[   37.474548] x27: 0000000000000000 x26: ffff800010004000
[   37.479858] x25: ffff800010000000 x24: 0000000000000018
[   37.485168] x23: 0000000000000001 x22: 0000000000000000
[   37.490479] x21: ffff0000f83acc58 x20: ffff0000f8dfa880
[   37.495789] x19: ffff80001181e160 x18: 0000000000000000
[   37.501099] x17: 0000000000000000 x16: 0000000000000000
[   37.506409] x15: 0000000000000000 x14: 0000000000000000
[   37.511719] x13: 0000000000000001 x12: 0000000000000002
[   37.517029] x11: 071c71c71c71c71c x10: 0000000000000040
[   37.522339] x9 : ffff8000118018e8 x8 : ffff8000118018e0
[   37.527649] x7 : ffff0000f60002c0 x6 : 0000000000000000
[   37.532959] x5 : ffff0000f6000248 x4 : 0000000000000000
[   37.538269] x3 : 0000000000000000 x2 : ffff80001195cd30
[   37.543579] x1 : 0000000000000018 x0 : ffff800012a70018
[   37.548889] Call trace:
[   37.551337]  mx3_gpio_irq_handler+0x3c/0xe8
[   37.555518]  generic_handle_irq+0x24/0x38
[   37.559528]  __handle_domain_irq+0x60/0xb8
[   37.563622]  gic_handle_irq+0x5c/0x148
[   37.567369]  el1_irq+0xb8/0x180
[   37.570510]  cpuidle_enter_state+0x84/0x360
[   37.574691]  cpuidle_enter+0x34/0x48
[   37.578265]  call_cpuidle+0x18/0x38
[   37.581751]  do_idle+0x1e4/0x288
[   37.584978]  cpu_startup_entry+0x20/0x80
[   37.588901]  rest_init+0xd4/0xe0
[   37.592128]  arch_call_rest_init+0xc/0x14
[   37.596135]  start_kernel+0x408/0x440
[   37.599799] Code: f9400a80 f9400441 b9401821 8b010000 (b9400000)
[   37.605896] ---[ end trace 6d25bb48dcb446ec ]---
[   37.610511] Kernel panic - not syncing: Fatal exception in interrupt
[   37.616863] SMP: stopping secondary CPUs
[   37.621072] Kernel Offset: disabled
[   37.624558] CPU features: 0x00002,2000200c
[   37.628651] Memory Limit: none
[   37.631706] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---

Question:

  1. Can we use GPIO pins as interrupt on M7? (It is possible, but I want to know it is advisable or not because A53 is also using IRQ and it will conflict if both will try to access IRQ Register at a same time.)
  2. Do I have to make any changes to Linux Kernel Source Code to make it work?
  3. Since I am using RDC as semaphone, do I have to configure Linux Source to make RDC (as semaphone) work properly on A53 ?

Thanks,

Aditya
.
.
.

Attachments:

  1. sourcecode.c - M7 Source Code

sourcecode.c (5.3 KB)

Usefull Details:

  • Machine Details: Toradex Verdin iMX8M Plus WB 1.1A on Verdin Development Board
  • Linux Kernel Details: Linux version 5.4.193-5.7.2-devel+git.b60d3160fd04 (oe-user@oe-host) (gcc version 9.5.0 (GCC)) #1 SMP PREEMPT Fri Dec 23 15:47:24 UTC 2022

Yes, you can, but

indeed you have to disable whole &gpio, especially when using interrupts. Linux GPIO driver will choke when it will see unexpected interrupt, which Linux didn’t enable. Either find a way if any to make this interrupt not reaching Linux or disable whole &gpio. You could as well make Linux ignoring that unexpected interrupt, but then what’s the point to moving it to CM, Linux performance still may suffer handling this unexpected interrupt.

It would be the best to to figure which &gpio bank can be dedicated to CM only and use pins from that bank on CM.

There’s as well partially finished gpio-rpmsg driver (primarily done for imx7ulp, for which NXP finally noticed the need for better sharing GPIO module between Cortex-M and CA. ). Using that driver you could disable real &gpio on Linux and define another one &gpio, which would send RPMSG messages instead of direct I/O to GPIO, Cortex-M will do physical writes/reads to GPIO and send RPMSG messages to CA when interrupt happens. All GPIO pins references from disabled &gpio could be easily remapped to virtual GPIO. libgpiod with Linux gpio-imx-rpmsg.c driver

1 Like

@Edward Thanks for the fast reply.

There are many challanges we have to face when we modify kernel and every time we want to upgrade OS, we have to repeatedly modify and test the kernel.
So, It can be our last option if we couldn’t find easy solution.

It is a good way, but seems like unfinished from NXP side (Reference: Solved: libgpiod with Linux gpio-imx-rpmsg.c driver - NXP Community).
Also, I was unable to find proper documentation and Cortex-M7 Example in iMX8M Plus SDK.

It is the best option. :clap:
But would be challenging. I need more than 40 GPIOs. So, I have to disable atleast 2 GPIO nodes.
To make it possible, I have to change hardware routing of other peripherels.

Getting_Started_with_Multicore_Programming_for_i.MX_6SoloX_V0.pdf (733.0 KB)

Found this document from NXP’s website.
Although it is for i.MX 6SoloX, it also stands true for i.MX 8M Plus.

I found it very useful to understand my problem.

Page:3

image

Page:14

image

image

Page:15

image

Seems like, it is a known problem. But solution is not well implemented !! :frowning_face:

Yes, it is.

Yes, not fully finished and not populated to other SDK’s. I guess only imx7ulp SDK supports it. And RPMSG GPIO stuff in that SDK is hard to separate from other code… But that’s the way to go if you really need to share CM-CA un-shareable GPIO.

If on Linux you don’t need any GPIO interrupts for particular GPIO bank, then you could just remove interrupt assignments in device tree for that bank.
On iMX7 (I hope on iMX8M as well, i don’t know), each &gpio has two interrupts, one for 0-15 pins and another one for 16-31. Current Linux GPIO driver will work if you just remove 2nd interrupt. Driver will think that just 16 pins are available in the bank. So that you could use those 16-31 pins on CM. Unfortunately interrupt order can’t be swapped without driver mods.

Clearly NXP should redesign GPIO to let dedicate every single GPIO to CM or CA. Write access should be restricted to one side, read access should be allowed to both sides.

Edward

2 Likes

Thanks @Edward This solves our problem! :clap:
There are many ways to solve this issue but my team found this easy.

We have to changes routing of our Custom Carrier Board and disable whole banks - &gpio3 and &gpio4 in Device Tree to make GPIO Interrupt work on Cortex-M7.

Reference:

Re: IMX8M PLUS: GPIO Interrupt conflicts beetween … - NXP Community

I have posted the similer thread on NXP Community which confirms the same.

Similar Problems:

Solved: Re: imx8mm M4 vs Linux gpio interrupt flag clear - NXP Community

Solved: libgpiod with Linux gpio-imx-rpmsg.c driver - NXP Community

IMX8M Mini: Sharing GPIO block between A53 and M4 - NXP Community