Conflict between SPI and GPIO

Hi there!
I’m working with imx7D and I’m using cortex A7 with Linux and M4 with FreeRTOS. In my project, i have to control some leds via SPI with linux and control gpio4_19 and gpio4_22 on M4 side. I’m using ECSPI3, witch corresponds to gpio4_8 to gpio4_11, and every time I access /dev/spidev2.0 to write new bits to change my leds color, my signals on gpio4_19 and gpio4_22 get cleared (go to zero). In other words, every time I try to change my leds somehow the other pins from gpio4 bank are filled with zeros.
I would like to know if the is some configuration I should do on my device tree, or something while using spidev (like an AND mask to the bits that shouldn’t be accessing), or another way to use spidev to avoid this conflict.

Hi @vhmm100,

It is a problem of GPIO port sharing between A7 and M4.

RDC semaphores could be used to lock GPIO port temporarily, change it and unlock, on both cores the same way, eliminating all side effects of concurrent port access, except additional jitter due to other side activity. Unfortunately RDC is not implemented in any driver.

RDC semaphores wouldn’t solve GPIO interrupts issues. I mean situation when both Linux and M4 need to use GPIO module interrupts. Once interrupt is enabled, both cores will receive not very expected interrupts enabled for other pins on other core. And Linux driver even doesn’t support enabling just one half of interrupts. I mean GPIO on iMX7 has upper and lower side interrupts for gpio31…16 and gpio15…0.

ECSPI can be eliminated from GPIO equation. Unless you modified DT ecspi3 settings, SDO/SDI/SCK pins already are iomuxed as ECSPI pins, not as GPIO pins. The only GPIO pin left is CS pin. It as well can be iomuxed as ECSPI pin (in DT MX7D_PAD_I2C2_SDA__ECSPI3_SS0 instead of MX7D_PAD_I2C2_SDA__GPIO4_IO11). Though there’s a “small” problem with ECSPI driver. Either you need to disable DMA or not send messages longer than 64 bytes (, which is basically the same, up to 64 bytes DMA is not used anyway). If you keep DMA enabled, in long transfers ECSPI will pulse HW CS pin every 8/16 or 32 SCK pulses. This is why by default GPIO CS is used instead of ECSPI HW CS.

If 64 bytes or no DMA suits you, change CS pin muxing as said above and empty or remove cs-gpios property of ecspi3, so that HW toggled SS0 is used as CS:

&ecspi3 { 
      cs-gpios = <0>;
      /delete-property/ dma-names;

Even if you solve GPIO4 -ECSPI3 issues with this, you should review whole device tree for all &gpio4 instances. Modules, which use it will be affected with your M4 FW ( unless you are only reading GPIO on M4 and not writing it).

It is the best to remove whole GPIOx from DT and dedicate it to M4. Usually not easy since so many gpios belong to the same GPIO.

My favorite solution for this problem is gpio-imx-rpmsg driver. You remove real GPIO from DT and create RPMSG GPIO instance, all references to your former GPIO in DT should point to newly created RPMSG GPIO. Linux driver instead of directly accessing GPIO sends requests to M4, when GPIO interrupts happen on M4, it sends RPMSG messages to Linux RPMSG GPIO driver, etc. Unfortunately several problems with this. 1. Official NXP driver is incomplete, if you are interested here my latest fixed driver for it. 2. Since mature rpmsg-tty comms are always required, I see no choice than upgrading from single-virtio RPMSG to as many virtios as you wish RPMSG-lite. One virtio would be used for rpmsg-gpio, another one for rpmsg-tty, etc. Rpmsg-lite is worth of upgrading, but there’s no support for it for imx7.
3. SRTM (piece of SW, which runs on M4 to service rpmsg-gpio and other similar rpmsg tasks) seems being included only in imx7ulp MCUXpresso SDK. Perhaps it is available for newer imx8, but certainly it is not available for imx7.

Edit: valid native (native CS, terminology used in kernel docs spi-controller.yaml) cs-gpios value is not <>, but <0>. For example having two CS’s like on Aster board, making first one native, 2nd gpio, like cs-gpios = <0>, <&gpio4 23 GPIO_ACTIVE_HIGH>; only <0> for 1st CS won’t break 2nd CS.

1 Like

Hi Edward! I’m sorry for the late answer.
After considering your reply and studying the possibilities, I realised that the best option for my project was to migrate the spi from linux to M4 and deny A7 access to the spi3 pins via RDC. We used the ecspi driver from toradex FreeRTOS as a base and changed a few things, like controlling CS as a GPIO (clearing and setting it).

Thanks for your help and availability, see you!