VF61 UARTB RTS Pin - Device Tree

Hello,

On my module, UARTB RTS is SODIMM pin 34, but I would like to use SODIMM 101 for this function instead. Our custom hardware is already wired this way for legacy reasons, (GPIO47 wired to RTS of a RS485 chip) and we currently toggle the GPIO from user space to set/clear RTS, but its not fast enough for our latest application. The built-in RS485 support of the module IS fast enough (I’ve tested using the Evaluation Board and the normal RTS pin, using the right ioctl settings), and so I would like to use this without re-wiring our hardware. Currently SODIMM 34 is not wired to anything at all and it would be painful to rebuild our hardware, so I want SODIMM 101 to perform this function.

That brings me to changing the device tree as a way of telling the module, “Use SODIMM 101 as the uartb RTS pin” but I’m a bit out of my depth here and I cannot get it to work. I have read this document over and over, and most other device tree documentation linked in this forum, and I cannot get it to work.

I admittedly do not fully understand the device tree syntax, but I’m hoping something like the below would work, but its not working for me. Is this even a possible function for SODIMM 101 to perform? Any insight at all would be helpful.

Thanks

&iomuxc {
    vf610-colibri {
        pinctrl_uart2: uart2grp {
            fsl,pins = <
                VF610_PAD_PTD0__UART2_TX        0x21a2
                VF610_PAD_PTD1__UART2_RX        0x21a1
                VF610_PAD_PTC2__GPIO_47            0x21a2
                VF610_PAD_PTD3__UART2_CTS      0x21a1
            >;
        };
...
    };
};

Greetings,

Do you get any error messages/logs, or does it simply just not work?

As for your device tree modifications normally I’d suggest a pin which has an alternate function that is meant to act as an RTS for UART. But as you said for hardware reasons the normal default is not a good option here. That being said as far as I know I don’t see any reasons a GPIO can’t be substituted for such a task.

I have a couple ideas of what might be the issue here. First of all the GPIO pin you’re trying to use is also defined here in the device tree: vf-colibri.dtsi « dts « boot « arm « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules

It may be the case that this causes a conflict since there are two assignments for this pin, try removing it so that it’s only being assigned to the UART2 group.

My next idea is that certain UART interfaces need to be “told” that a GPIO is serving as the RTS pin. See this document to see what I mean: https://www.kernel.org/doc/Documentation/devicetree/bindings/serial/serial.txt

Finally it may also be the mode specifier. While 0x21a2 was the mode specifier for the default pin this does not necessarily mean it’s the correct one for a new GPIO pin. Though this one I’m less sure about and may need to check and get back to you on.

In any case try these suggestions and let me know if anything changes for you.

Best Regards,
Jeremias

Thanks for the response Jeremias.

I don’t get any errors messages or logs, and in fact the GPIO itself still works like normal, even when I tried to remove it from the device-tree as you mentioned. I’m wondering if there are good resources available for confirming the device tree on the unit itself?

As you can guess, I’m a device-tree novice, but I would like to try the avenue of “telling” the uart to use a GPIO as you noted in the second link. However, I’m confused reading that - would you mind posting a sample of what I might be looking to put in there in my use case, or explaining further?

Let me know what you find out about the identifier as well.

Thanks very much,
Alex

Unfortunately things like device tree tooling/debugging is not really a think currently. At the moment device tree development can be very much trial and error based.

As for the information in the 2nd link I provided, I assume you can locate UART2 node in the device tree and add the rts-gpios line. The syntax usually follows <&gpio(BANKNUMBER) (GPIONUMBER) GPIO_ACTIVE_LOW>;. So for that gpio I believe it’d be something like: rts-gpios = <&gpio0 47 GPIO_ACTIVE_LOW>;.

Let me check with some of my colleagues about this info too, as the kernel documentation I linked is for generic UART devices and also the vybrid based kernel is on the older side. So the information may not actually be applicable here.

Best Regards,
Jeremias

I tried adding the rts-gpios as noted, and no effect. I tried it with/without the pinctrl definition I noted above, and no change there. I’m not sure if one relies on the other or not. Note that I’m making all my changes in an overlay like “my-carrier.dts.” I know this is getting built into the image because if in my testing I have somtimes had a syntax error or something, and my build has failed, so I know for sure that my overlay is being added.

One thing that keeps sticking out to me here is that no matter what I put in the device tree, the GPIO still acts like it always has - a regular GPIO. I don’t know of a good way to remove it from the tree, besides redefining that “pinctrl_additionalgpio” node, and omitting GPIO47, which I did, and it had no effect. I would expect it to not be available as a GPIO to export, change direction and value, etc.

  • Is there a better way to make sure that the GPIO 47 definition is not included?
  • Have you had a chance to speak with your colleagues about the mode specifier and the rts-gpios?

Thanks for your continued help here.

  • Alex

Could you share your attempted overlay with these latest changes. It’s a little unclear from your description how you’re making the changes via overlay. Just want to make sure before I comment further.

Best Regards,
Jeremias

Sure thing, below is the latest thing I tried, which actually does not include redefining pinctl_additionalgpio as I mentioned above. I tried that earlier and then removed it to simplify things after it appeared to have no effect on the GPIO status.

/*
 * Copyright 2014 Toradex AG
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.\
 */

 /*
 A Test
 */

/dts-v1/;
#include "vf610-colibri.dtsi"
#include "vf-colibri-eval-v3.dtsi"

/ {
	model = "ATS/Toradex Colibri VF61 on Colibri Evaluation Board";
	compatible = "toradex,vf610-colibri_vf61-on-eval", "toradex,vf610-colibri_vf61", "fsl,vf610";
};

&i2c0 {
	clock-frequency = <100000>;
};


&uart2 {
    status = "okay";
    linux,rs485-enabled-at-boot-time;
    rs485-rts-active-low;
    rs485-rx-during-tx;
	rts-gpios = <&gpio0 47 GPIO_ACTIVE_LOW>;
	pinctrl-0 = <&pinctrl_uart2>;
};

&iomuxc {
     vf610-colibri {
         pinctrl_uart2: uart2grp {
             fsl,pins = <
                 VF610_PAD_PTD0__UART2_TX       0x21a2
                 VF610_PAD_PTD1__UART2_RX       0x21a1
                 VF610_PAD_PTC2__GPIO_47		0x21a2
                 VF610_PAD_PTD3__UART2_CTS      0x21a1
             >;
         };
	 };
};

While I don’t see anything immediately wrong with your device tree code, one observation I had was that for rts-gpios, you use gpio0. Normally with our other modules the GPIOs are separated into multiple GPIO banks starting with 0.

However for the vybrids I believe there is no GPIO banks, or rather there is only 1 bank. After going through the vybrid device tree. I noticed similar GPIO entries use gpio1, like at this line: vf-colibri.dtsi « dts « boot « arm « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules

This leads me to think that the single vybrid GPIO bank starts at 1 rather than 0. So this all all to say, try rts-gpios = <&gpio1 47 GPIO_ACTIVE_LOW> instead.

Finally one more thing you can try as more of a sanity check is try making these changes directly to the source device tree files rather than trying to overwrite with your own file on top. There’s no easy way to debug device tree files so it’s hard to tell what’s going on sometimes. While it certainly does seem like your file is being included in the compilation it may not be overlaying/overwriting like you think it is.

Best Regards,
Jeremias

Hi Jeremias,

I finally got back to this and made some progress. I went back to basics and am using the base image, and editing the source device tree files directly. You were correct that they were not overwriting as thought they were, and now I can confirm the device tree that I am getting using the whatever.dtb.dts.tmp as noted here. Using this method I confirmed that there are not duplicate definitions of the pins that I care about anymore.

So, I’ve been working directly in vf-colibri.dtsi and I

a) removed the GPIO_47 definition from pinctrl_hog_0.
b) changed UART2_RTS to GPIO_47 in pinctrl_uart2
c) changed &uart2 node as below

&uart2 {
	linux,rs485-enabled-at-boot-time; 
	rs485-rts-active-low; 
	rs485-rx-during-tx;
	rts-gpios = <&gpio1 47 GPIO_ACTIVE_LOW>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart2>;
};

Sadly, this does not do the trick. It DOES deactivate the existing RTS line, so that part works, but if I wire up to the GPIO47 I get no change out of that, so something is still not right.

For the record, I am testing this on the module, hooked into the colibri evaluation board, by taking a formatted SD card, and updating the vf610-colibri-eval-v3.dtb and zImage files, then running the following at uboot

run setupdate
run prepare_ubi
run update_fdt
run update_kernel

Then I am using a scope on the pins to see if the GPIO pin is behaving as the RTS does under normal device tree.

I have attached the compiled .dtb.dts.tmp file here in case that is helpful. You can see in there that values for the GPIO pin(0x0BC 0x000 0x0 0x0 as you can find in vf610-pinfunc.h) are indeed subsituted in the uart2 pinctrl nod, and are not found anywhere else.

Thank you for your continued help on this.

Actually on further research I think I have an idea what’s going on here. So the Vybrids use a similar driver (fsl_lpuart) to control their UARTs as does the newer i.MX8 line. There was a reported issue a while ago that this driver driver for the i.MX8 doesn’t have support to handle the rts-gpios property. I imagine this is the case here since if the i.MX8 didn’t have this support in the newer kernel then I doubt the Vybrids have this support as well.

Hmm let me bring this up with the development team as it seems we’re limited by the driver itself.

Best Regards,
Jeremias

Ah, I see. Well, I look forward to hearing what the development team has to say here. It would be disappointing if this turns out to not be possible, but I would certainly feel better knowing there is a concrete reason this won’t work.

Hi @jeremias.tx - is there any word from the dev team on this? Or perhaps a timeline for when we might expect them to weigh in?

Thanks,
Alex

No words on a timeline yet. The issue does exists in their backlog currently. Unfortunately due to the difference in kernel versions between the i.MX8 and Vybrid, the effort to do this for the i.MX8 might not carry over much at all to the Vybrid. Therefore it’s still quite unknown the time and effort needed to add this feature to the uart driver.

Best Regards,
Jeremias

Thanks for the update @jeremias.tx. Just to be clear - remapping a GPIO as RTS is confirmed as not possible on the Vybrid with the current driver?

We’re pretty sure it’s not. The team already confirmed this on the i.MX8 and the Vybrids use an even older version of the same UART driver from NXP. This is to say if this capability is present in the recent version of the driver it’s most likely not possible with whatever older version of the driver Vybrid uses.

@jeremias.tx - Do you know if this fix was integrated on any of the development branches for the i.MX8 line? I am running into a similar problem with my custom hardware.

Hi @mu.jn,

As far as I can tell NXP hasn’t added this functionality to their “lpuart” driver that the i.MX8 uses. To clarify, are you using our Apalis i.MX8 module?

Best Regards,
Jeremias

Yeah, I dug into the fsl_lpuart.c driver and confirmed that it does not support gpio RTS. I made a local patch for our use case, so it now works for our application. Thanks!