Disabling Iris Ports B & C RS232 driver

We have a proyect where we use an imx7d colibri module mounted on an Iris v2 board. We are using port B in our Yocto linux image to comunicate with a motor controller board on a RS485 bus. We have designed an extension board for the Iris that provides de RS485 driver and it works fine most of the time. From time to time this Port B stops receiving. We had disabled the Ports B & C Iris RS232 driver by clearing the GPIO2.IO[27] in the M4 auxiliary CPU firmware and modified the device tree so that linux would not make use of this GPIO2 pins with no success so far. Linux takes control of this pin and enables de driver. I have thoroughly reviewed all the device tree source files and have not been able to find where this pin is used. I have also tried in linux to export this pin using the sysfs gpio interface in order to control it from my motor control routine in my linus app. Could not even get the pin exported as linux is already using it somewhere.

Could you guide me so that I could stop linux from enabling this driver?

Regards,

Ignacio

See imx7-colibri.dtsi:

	pinctrl_gpio1: gpio1-grp {
		fsl,pins = <
                    ...
			MX7D_PAD_EPDC_GDSP__GPIO2_IO27		0x14 /* SODIMM 104 */

But it won’t help you if you remove this single line from pinctrl_gpio1. I saw phenomenon like you. It happens when A7 and M4 simultaneously write access GPIO port latch. To eliminate this problem reliably you have just a two choices I know.

  1. Simplest one. Find GPIO port (any one gpiochip gpioN available on imx7 out of available gpio1/2/…7 ) not used Linux as GPIO. Any peripheral devices which toggle pins HW-vise, like SPI TX / RX / CLK or UART RX /TX are OK. Those which are bit banged by software are not OK. Read only pins are good as well.

  2. NXP for their imx7ulp, on which Cortex-M is master and Cortex-A is slave, had to solve bunch of communications problems, audio streaming, etc etc, as well GPIO. That’s just my guest, perhaps something else pushed them to create gpio-imx-rpmsg driver…
    You have an idea already, isn’t it? Having RPMSG GPIO working, you just replace gpioN in device tree with RPMSG variant. You dedicate whole gpioN to M4 and let A7 access it via RPMSG, along with GPIO interrupts.
    Actually there are many problems with this. FreeRTOS with examples provided kindly by Toradex uses older RPMSG code, which allows single RPMSG device. As you may guess, RPMSG GPIO would consume one RPMSG, but you have your own needs for A5-M4 communications, so you need at least two RPMSG devices. Newer FSL/NXP RPMSG-lite allows having as many RPMSG devices as you wish. So you need to at least switch to RPMSG lite.
    You need not only RPMSG lite, but as well RPMSG GPIO support code on M4 side. MCUxpresso provides this code in imx7ulp BSP. Code is tightly coupled witch bunch of code, which you don’t need on imx7d, shaving useless parts isn’t simple.
    And the last one problem. gpio-imx-rpmsg interrupts support was not complete. I managed to fix it, patch is available on NXP forums. Even though you may not use GPIO interrupts on M4, moving shared gpioN to M4 it is quite likely that some pins are used with interrupts on Linux side.

HTH
Edward

1 Like

Hi @IgnacioF,

Could you please share more information about your problem with us?

  • What version of iMX7D are you using?
  • What modification have you done with your device tree? Could you share your DTS file with us?
  • Finally, what is your objective with these modifications? If I understand correctly, sometimes Linux takes over control of your port that is been used by M4, so it just stops working. Am I correct?

Best regards,
Hiago.

Hi Hiago, I have enclosed the versions of the Colibri module and Iris Board I am using for this proyect and the modified DTS file.

I need to disable the RS232 driver on the Iris board because I have an RS485 driver connected to PortB throught the Iris X14 connector. This can be done by clearing GPIO2.IO[27] ( SODIMM#104) and I am doing it on my M4 firmware and it works, but when linux is loaded on the A7 processors some driver takes control of the pin and enables the RS232 driver. I have tried another approach, trying to clear the pin from my linux software without success because the pin is not available for the sysfs gpio interface. When I try to export this pin, linux kernel replies the pin is already taken.

Could you guide me in how can I get that linux does not take control of this pin ?

Regards,

Ignacio

imx7d-colibri-ebers-niec.dts (2.04 KB)

Hi Edward, I have already tried to avoid linux taking control of this pins by adding this lines:
&iomuxc
{
pinctrl_gpio1: gpio1-grp
{
fsl,pins = <>;
};
};

It doesn’t work :frowning:

I am not sure of what you proposed in option 1. Is it that I include in my dts file something like this:

/ {
model = “Toradex Colibri iMX7D on Colibri Iris V2 Board”;
compatible = “toradex,colibri-imx7d-iris-v2”,
“toradex,colibri-imx7d”,
“toradex,colibri-imx7d”,
“fsl,imx7d”;
soc
{
aips1: aips-bus@30000000
{
gpio2: gpio@30210000 {};
};
};
};

Hi @IgnacioF

I want to make 2nd attempt explaining what really happens. No, it isn’t some Linux driver, it is at the one hand nature of imx7 gpio controller. imx7 gpio doesn’t have means to toggle dedicated pins simultaneously and concurrently from different threads and cores (there are such means for example on VF family, dedicated register to set pins, clear pins and toggle pins). On imx7 you have single data register for whole bunch of 32 data pins. Bad things happen when both A7 and M4 concurrently modify bits in the same 32bits register. There are various scenarios how shared GPIO port make harm both sides, M4 and A7. For example one core reads register 000, flips bit in memory 001, another core reads the same 000 since first code haven’t yet write new value back to register. First code writes 001 back to register. Second code flips its own bit 010 and writes 010 to register. Intended write of first code is lost…

Imx7 has resource domain controller (RDC) and no single driver in Linux to support it. RDC is not only limits access from another code, it also allows concurrent resource locking. So A7 could RDC lock GPIO, flip bits, unlock RDC. M4 could do the same. Unfortunately no drivers for this.

Like I wrote previously, you should try finding 32bits GPIO, which is not used at all in Linux. Then you could safely toggle GPIO bits from M4.
If all your needs are disabling those Iris Ports, then you should do it from Linux. You can’t safely toggle GPIO bits on M4, unless Linux doesn’t use the same GPIO port.

Hi Edward, I think I have not made myself clear about what my needs are. I don’t need to control this gpio pin from both cores and I cannot choose another pin because this is the pin that Toradex chose for enabling/disabling the RS232 driver in the Iris board.
What I need is to clear this pin so the driver is disabled and stop linux from re-enabling the driver afterwards. I do not care whether this can be done by the M4 core or the A7 cores.

Thanks

Ignacio

This should work.

gpioset `gpiofind “SODIMM_104”`=0

Hi @IgnacioF,

Were you able to solve your issue?

As @Edward said (thanks Edward for your help), you can disable the UART-B/C RS-232 by setting the 104 SODIMM pin to low, as stated on the Iris v2.0 datasheet:

You can find more about it here: https://docs.toradex.com/108421-colibri_arm_iris_carrier_board_datasheet.pdf

Let me know if this solved your issue.

Best regards,
Hiago.

No, this does not solve my problem because I already knew this and I was already clearing this GPIO from the M4 firmware. I have also tried to change the state of the pin from Linux using the instructions that Edward suggested with no result, I got this error messages:

  • ~# gpioget $(gpiofind “SODIMM_104”)
    gpioget: error reading GPIO values: Device or resource busy
  • ~# gpioset $(gpiofind “SODIMM_104”)=0
    gpioset: error setting the GPIO line values: Device or resource busy

Apparently Linux kernel was using this pin and I couldn’t find where this use was defined in the different device tree source files until this morning.

I have searched again through the device tree source files and in the “imx7-colibri-iris-v2.dtsi” file I found this:

&gpio2 {
	/*
	 * uart_b_c_on_x14_enable turns the UART transceiver for UART_B and
	 * UART_C on. If one wants to turn the transceiver off, that property
	 * has to be deleted and the gpio handled in userspace.
	 * The same applies to uart_a_on_x13_enable where the UART_A
	 * transceiver is turned on.
	 */
	uart_b_c_on_x14_enable {
		gpio-hog;
		gpios = <27 GPIO_ACTIVE_HIGH>; /* SODIMM 104 */
		output-high;
	};
};

&gpio5 {
	uart_a_on_x13_enable {
		gpio-hog;
		gpios = <17 GPIO_ACTIVE_HIGH>; /* SODIMM 102 */
		output-high;
	};
};

So I have tried adding this to my dts file:

&gpio2 {
	uart_b_c_on_x14_enable {
		gpio-hog;
		gpios = <27 GPIO_ACTIVE_HIGH>; /* SODIMM 104 */
		output-low;
	};
};

And voila now Linux is clearing this GPIO and disables the RS2332 driver as I needed. So now my problem is solved.

@IgnacioF,

Thanks for your feedback. My fault, I tried with eval-v3 dtb on Iris board, sorry.

@hfranco.tx,

I didn’t know it’s possible to force some GPIO output high or low via DT. But speaking about Iris DT, how one is supposed to switch RS232 drivers on/off from user space? libgpiod won’t work with pin, which is “output-low” or “output-high” in DT. The same with sysfs GPIO. I’d remove those “uart_b_c_on_x14_enable” from DT. Pull down resistor on these pins are enough to make RS232 drivers enabled by default, no need to force them low in DT.

Thanks
Edward

1 Like

Hello @Edward,
The idea of the standard device trees is that they should make the hardware on the carrier board work well. Because the RS232 drivers are populated on the iris, it makes sense that the pins are explicitly setup on the initialization and that we don’t rely on default configuration of the pins for the functionality to be correct.
If something needs to be customized (like disabling the RS232 driver), this can always be done by a custom device tree like @IgnacioF has done.
If someone needs to dynamically disable / enable the drivers from user space, this can also be done by removing the gpio-hog elements on the custom device tree and then using the standard gpiolib tools to drive the pins.

Best regards,
Rafael Beims