Device Tree for UART in DCE Mode for iMX6ULL module

This question is in continuation of my old question. I am using toradex colibri iMX6ULL system-on-module on my custom board which is based on viola board of toradex.

I am struggling with UART, GPIOs of my custom board. I have solved the SPI issue on my board but later I got to know about another issue with my board and that’s why I thought to ask a new question.

I am able to activate desired UART port and SPI port for my board. But I got to know that my peripheral sensors which are connected to the toradex module colibri imx6ull has TX and RX lines swapped. I was trying to swap tx rx pins of UART5 of the imx6ull soc. For that, I am trying to enable DCE Mode for uart5. However, when i define (redefine) pinctrl-0 and pinctrl-name properties in my upper dts file, then uart tty port under /dev/ directory disappears. I have tried to point pinctrl-0 to pinctrl_uart5_their and pinctrl_uart5_own. The pinctrl_uart5_their is copy of pinctrl_uart5 defined in imx6ull-colibri.dtsi file.

GPIOs are also not working properly. I tried to test them by exporting them by following a guide on toradex developer site and writing 1 and 0 after changing the direction using appropriate commands but it doesn’t work for me as output is not reflected on the pins.

Please help me by verifying my device tree and suggesting me the right way to do it.

The device tree is over here:Just to inform you our latest results. In DCE mode, we have been able to transmit data via UART5 but receiving is not working.

I think may be this question can help us in getting the solution: UART3, UART4, UART5 on imx6ull - NXP Community

/dts-v1/;
#include "imx6ull-colibri-nonwifi.dtsi"
#include "imx6ull-colibri-eval-v3.dtsi"

/ {
	model = "Toradex Colibri iMX6ULL 256MB on Colibri Evaluation Board V3";
	compatible = "toradex,colibri_imx6ull-eval", "fsl,imx6ull";


	gpio_additional {
		pinctrl-name = "default";
		pinctrl-0 = <&pinctrl_additionalgpio>;
		status = "okay";
	};
};


&iomuxc {
	imx6ull-colibri {
		pinctrl_additionalgpio: additionalgpios {
			fsl,pins = <
				MX6UL_PAD_UART2_RTS_B__GPIO1_IO23 0x14 		// Pin 34 => GPS SafeBoot
				MX6UL_PAD_CSI_DATA00__GPIO4_IO21  0x14 		// Pin 101 => 1V8 Power Supply Enable
				MX6UL_PAD_LCD_ENABLE__GPIO3_IO01  0x14 		// Pin 44 => GPS EXINT
				MX6UL_PAD_LCD_DATA07__GPIO3_IO12  0x14 		// Pin 46 => GPS RST
				MX6UL_PAD_LCD_DATA09__GPIO3_IO14  0x14 		// Pin 48 => UNUSED
				MX6UL_PAD_LCD_DATA06__GPIO3_IO11  0x14 		// Pin 80 => SX1301 RST
			>;
		};
	};

	pinctrl_uart5_their: uart5grp_their {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO04__UART5_DTE_RX	0x1b0b1
			MX6UL_PAD_GPIO1_IO05__UART5_DTE_TX	0x1b0b1
		>;
	};

	pinctrl_uart5_own: uart5grp_own {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO05__UART5_DCE_RX	0x1b0b1
			MX6UL_PAD_GPIO1_IO04__UART5_DCE_TX	0x1b0b1
		>;
	};
};


&uart1 {
	status = "okay";
};

&uart2 {
	status = "okay";
	/delete-property/fsl,dte-mode;
	fsl,dce-mode;
};

&uart3 {
	status = "disabled";
};

&uart4 {
	status = "disabled";
};

&uart5 {
	status = "okay";

	pinctrl-name = "default";
	pinctrl-0 = <&pinctrl_uart5_own>;

	/delete-property/fsl,dte-mode;
	fsl,dce-mode;
};


&ecspi1 {
	status = "okay";
};

&i2c1 {
	status = "okay";

	/* M41T0M6 real time clock on carrier board */
	rtc: m41t0m6@68 {
		status = "disabled";
	};
};


&pwm1 {
	status = "okay";
};

&pwm2 {
	status = "okay";
};


&lcdif {
	status = "disabled";
};

&ecspi1 {
	status = "okay";
};

&mcp258x0 {
	status = "disabled";
};

&spidev0 {
	status = "okay";
};

EDIT:

I have resolved the issue of UART port being disappeared. This was issue with my device tree as my pinctrl_uart5_their nodes weren’t under imx6ull-colibri node (see iomuxc in device tree above).

But I am not able to swap the TX RX Pins of UART5 with DTB. I have found few posts which says it is possible. Also, GPIOs are not working according to the comment mentioned on your GPIO guide. Find the snapshot of my terminal below:

root@colibri-imx6ull:~# echo 75 > /sys/class/gpio/export                        
root@colibri-imx6ull:~# echo "out" > /sys/class/gpio/gpio75/direction           
root@colibri-imx6ull:~# echo 1 > /sys/class/gpio/gpio75/value                   
root@colibri-imx6ull:~# echo 1 > /sys/class/gpio/gpio75/value                   
root@colibri-imx6ull:~# echo 0 > /sys/class/gpio/gpio75/value                   
root@colibri-imx6ull:~# echo 1 > /sys/class/gpio/gpio75/value                   
root@colibri-imx6ull:~# cat /sys/kernel/debug/gpio                              
gpiochip0: GPIOs 0-31, parent: platform/209c000.gpio, 209c000.gpio:             
 gpio-2   (                    |VCC_USB[1-4]        ) out lo                    
 gpio-11  (                    |enable              ) out hi                    
                                                                                
gpiochip1: GPIOs 32-63, parent: platform/20a0000.gpio, 20a0000.gpio:            
                                                                                
gpiochip2: GPIOs 64-95, parent: platform/20a4000.gpio, 20a4000.gpio:            
 gpio-75  (                    |sysfs               ) out hi                    
 gpio-90  (                    |spi_imx             ) out hi                    
                                                                                
gpiochip3: GPIOs 96-127, parent: platform/20a8000.gpio, 20a8000.gpio:           
                                                                                
gpiochip4: GPIOs 128-159, parent: platform/20ac000.gpio, 20ac000.gpio:          
 gpio-128 (                    |cd                  ) in  lo                    
 gpio-129 (                    |Wake-Up             ) in  lo                    
 gpio-130 (                    |id                  ) in  lo                    

Pin 80 in SODIMM pin corresponds to Kernel number 75.

The latest device is below:

/dts-v1/;

#include "imx6ull-colibri-nonwifi.dtsi"
#include "imx6ull-colibri-eval-v3.dtsi"

/ {
	model = "Toradex Colibri iMX6ULL 256MB on Colibri Evaluation Board V3";
	compatible = "toradex,colibri_imx6ull-eval", "fsl,imx6ull";


	gpio_additional {
		pinctrl-name = "default";
		pinctrl-0 = <&pinctrl_additionalgpio>;
		status = "okay";
	};
};


&iomuxc {
	imx6ull-colibri {
		pinctrl_additionalgpio: additionalgpios {
			fsl,pins = <
				MX6UL_PAD_UART2_RTS_B__GPIO1_IO23 0x14 			// Pin 34 => GPS SafeBoot
				MX6UL_PAD_CSI_DATA00__GPIO4_IO21  0x14 			// Pin 101 => 1V8 Power Supply Enable
				MX6UL_PAD_LCD_ENABLE__GPIO3_IO01  0x14 			// Pin 44 => GPS EXINT
				MX6UL_PAD_LCD_DATA07__GPIO3_IO12  0x14 			// Pin 46 => GPS RST
				MX6UL_PAD_LCD_DATA09__GPIO3_IO14  0x14 			// Pin 48 => UNUSED
				MX6UL_PAD_LCD_DATA06__GPIO3_IO11  0x14 			// Pin 80 => SX1301 RST
			>;
		};
	

		pinctrl_uart5_their: uart5grp_their {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO04__UART5_DTE_RX	0x1b0b1
				MX6UL_PAD_GPIO1_IO05__UART5_DTE_TX	0x1b0b1
			>;
		};

		pinctrl_uart5_own: uart5grp_own {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO04__UART5_DCE_TX	0x1b0b1
				MX6UL_PAD_GPIO1_IO05__UART5_DCE_RX	0x1b0b1
			>;
		};

	};
};


&uart1 {
	status = "okay";
};

&uart2 {
	status = "okay";
	/delete-property/fsl,dte-mode;
	fsl,dce-mode;
};

&uart3 {
	status = "disabled";
};

&uart4 {
	status = "disabled";
};

&uart5 {
	status = "okay";

	pinctrl-name = "default";
	pinctrl-0 = <&pinctrl_uart5_own>;

	// /delete-property/fsl,dte-mode;
	// fsl,dce-mode;
};


&ecspi1 {
	status = "okay";
};

&i2c1 {
	status = "okay";

	/* M41T0M6 real time clock on carrier board */
	rtc: m41t0m6@68 {
		status = "disabled";
	};
};


&pwm1 {
	status = "okay";
};

&pwm2 {
	status = "okay";
};


&lcdif {
	status = "disabled";
};

&ecspi1 {
	status = "okay";
};

&mcp258x0 {
	status = "disabled";
};

&spidev0 {
	status = "okay";
}; 

Edit (20.08.2018 13:10)

Just to inform you our latest results. In DCE mode, we have been able to transmit data via UART5 but receiving is not working.

I think may be this question can help us in getting the solution: UART3, UART4, UART5 on imx6ull - NXP Community

Hi @abhiarora

Could you provide the version of the hardware and software of your module? A complete serial bootlog of the module would be very helpful.

Thanks and best regards, Jaski

Hardware: Colibri iMX6ULL 256 MB V1.0A

Software: Linux colibri-imx6ull 4.9.84-2.8.2+gb2a7f2f #1 SMP armv7l GNU/Linux (uname -a)
The boot log is over here

It gets a bit confusing when handling two issue in one thread, please open two threads next time.

As for the UART problem: There is no fsl,dce-mode (see Documentation/devicetree/bindings/serial/fsl-imx-uart.txt). If fsl,dte-mode is not present DCE mode is assumed. From all what I can tell your device tree above looks correct to me, you are muxing in DCE mode and did not set the fsl,dte-mode property.

The linked article refers to mux/daisy channing issue, but looking at the mux preprocessor defines in arch/arm/boot/dts/imx6ul-pinfunc.h it looks good:

#define MX6UL_PAD_GPIO1_IO04__UART5_DCE_TX		0x006c 0x02f8 0x0000 8 0
...
#define MX6UL_PAD_GPIO1_IO05__UART5_DCE_RX		0x0070 0x02fc 0x0644 8 3

The RX daisy chaining register 0x0644 is correctly set to 3 (GPIO1_IO05_ALT8).

Maybe the issue is related to hardware flow control? Did you make sure to disable hardware flow control on both sides? (e.g. stty -F /dev/ttymxc4 -crtscts).

Regarding GPIOs:

The pinctrl node looks good. However, you cannot create a random node in the device tree and assign it a pinctrl node. Since the gpio_additional node has no compatible, the kernel won’t load a driver for it and hence won’t apply the pinctrl.

To mux GPIOs for device tree we usually use the iomuxc node itself (see arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi). You can overwrite the pinctrl settings as follows:

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2 &pinctrl_hog_3
		&pinctrl_hog_4 &pinctrl_hog_5 &pinctrl_hog_6 &pinctrl_additionalgpio>;
};

Also make sure that any of the pins you have in pinctrl_additionalgpio are not used anywhere else. E.g. MX6UL_PAD_UART2_RTS_B_.. is muxed in pinctrl_uart2. This will lead to a conflict. Typically the second driver which gets loaded will fail to load since the kernel cannot assign all pins.

In this case you have to create a pinctrl node where you only mux RX/TX pins, e.g.:

	minimal_pinctrl_uart2: uart2grp {
		fsl,pins = <
			MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX	0x1b0b1
			MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX	0x1b0b1
		>;
	};

And assign that to uart2:

&uart2 {
	pinctrl-names = "default";
	pinctrl-0 = <&minimal_pinctrl_uart2>;
};

I have done few experiment with uart5 and found out TX is working (module is able to transmit) but receiving is not working. I am using minicom with Hardware and Software flow control disabled. With DTE property, things work perfectly but without it and setting pinctrl-0 to DCE pins, only TX works.

Thanks for your suggestion for GPIO. I will try it.

Can you try my dts file on your system and help me with UART5 problem only?

Hi @abhiarora

We can reproduce the issue. We are working on this issue. We will come back soon to you.

Thanks. We are waiting for your reply.

Any success for the issue?

Unfortunately not. In mean time, you can switch TX/RX and use DTE Mode.

We have tried few experiments and found out Tx pin is working fine but Rx pin is not receiving anything. May be there is some bug in the driver?

So you mean also in DTE Mode, the RX is not working.

DTE mode is working perfectly fine. However, if we configure it in DCE mode. RX pin doesn’t work. However, TX pin is working.

we already know this and we are working on this issue. The workaround for you would be to switch RX/TX and use DTE mode meanwhile.

Hi

Our regular U-Boot already sets up UART5 to DTE mode. I guess that influences the pinmuxing later on in Linux.

You could try if stopping in U-Boot, setting UART5 to DCE mode and booting helps:

Hit any key to stop autoboot:  0
Colibri iMX6ULL # 
Colibri iMX6ULL # mw.l 021f4090 00000801 1
Colibri iMX6ULL # boot
Booting from NAND...

If so, then you will have to change U-Boot to make that permanent, e.g. don’t change the UFCR and UCR3 register of UART5 in setup_dtemode_uart():

diff --git a/board/toradex/colibri-imx6ull/colibri_imx6ull.c b/board/toradex/colibri-imx6ull/colibri_imx6ull.c
index b1558f0b72..5b0d585bd0 100644
--- a/board/toradex/colibri-imx6ull/colibri_imx6ull.c
+++ b/board/toradex/colibri-imx6ull/colibri_imx6ull.c
@@ -202,11 +202,11 @@ static void setup_dtemode_uart(void)
 {
 	setbits_le32((u32 *)(UART1_BASE + UFCR), UFCR_DCEDTE);
	setbits_le32((u32 *)(UART2_BASE + UFCR), UFCR_DCEDTE);
-	setbits_le32((u32 *)(UART5_BASE + UFCR), UFCR_DCEDTE);
+//	setbits_le32((u32 *)(UART5_BASE + UFCR), UFCR_DCEDTE);
 
	clrbits_le32((u32 *)(UART1_BASE + UCR3), UCR3_DCD | UCR3_RI);
	clrbits_le32((u32 *)(UART2_BASE + UCR3), UCR3_DCD | UCR3_RI);
-	clrbits_le32((u32 *)(UART5_BASE + UCR3), UCR3_DCD | UCR3_RI);
+//	clrbits_le32((u32 *)(UART5_BASE + UCR3), UCR3_DCD | UCR3_RI);
 }
 
 static void setup_iomux_uart(void)

Max

Can I add the boot command in uEnv.txt?

Sure, why not?

We want to use UART3 in DCE mode as well. Can you share it’s uboot command?

I meant DCE mode.

Could you ask a new Question please? Thanks.