Changing default U-Boot console to UART3 for Colibri iMX7 eMMC

Based on this answer, I am trying to change the console serial port from UART1 to UART3 (pins 19 and 21 based on Table 5-20 Colibri iMX7 reference doc).

I have rebuilt U-Boot after applying the below diff. Linux kernel is now correctly using UART3 for serial console (probably because of console=ttymxc2 environment variable which is changed correctly in U-Boot).

However, U-Boot is still using UART1 for its console and doesn’t output anything to UART3.

By comparing the codes for iMX6 modules, I have found a three major differences that could be the cause of this issue. The cause of this issue could be them, but also there could be a simple configuration that I am missing.

1. CONFIG_MXC_UART_BASE

The colibri_imx6.h defines the following macro:

#define CONFIG_MXC_UART_BASE		UART3_BASE

I wonder if a similar line should be added in colibri_imx7_emmc.h. Currently, CONFIG_MXC_UART_BASE is not defined in this file.

2. setup_dtemode_uart

The colibri_imx6.c calls setup_dtemode_uart function that sets up some registers, but colibri_imx7.c doesn’t have such function. Is this function needed for imx7?

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 *)(UART3_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 *)(UART3_BASE + UCR3), UCR3_DCD | UCR3_RI);
}

3. mxc_serial_platdata

Again in colibri_imx6.c, the uart port is defined as a U-Boot device using platform data:

static struct mxc_serial_platdata mxc_serial_plat = {
	.reg = (struct mxc_uart *)UART1_BASE,
	.use_dte = true,
};

U_BOOT_DEVICE(mxc_serial) = {
	.name = "serial_mxc",
	.platdata = &mxc_serial_plat,
};

Isn’t such thing necessary for iMX7 too?

Here is full diff of the changes I have made to U-Boot source:

diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c
index a8d8dbd..5f71967 100644
--- a/board/toradex/colibri_imx7/colibri_imx7.c
+++ b/board/toradex/colibri_imx7/colibri_imx7.c
@@ -59,11 +59,9 @@ int dram_init(void)
 	return 0;
 }
 
-static iomux_v3_cfg_t const uart1_pads[] = {
-	MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
-	MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
-	MX7D_PAD_SAI2_TX_BCLK__UART1_DTE_CTS | MUX_PAD_CTRL(UART_PAD_CTRL),
-	MX7D_PAD_SAI2_TX_SYNC__UART1_DTE_RTS | MUX_PAD_CTRL(UART_PAD_CTRL),
+static iomux_v3_cfg_t const uart3_pads[] = {
+	MX7D_PAD_UART3_RX_DATA__UART3_DTE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX7D_PAD_UART3_TX_DATA__UART3_DTE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
 };
 
 static iomux_v3_cfg_t const usdhc1_pads[] = {
@@ -208,7 +206,7 @@ static void setup_iomux_fec(void)
 
 static void setup_iomux_uart(void)
 {
-	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+	imx_iomux_v3_setup_multiple_pads(uart3_pads, ARRAY_SIZE(uart3_pads));
 }
 
 #ifdef CONFIG_FSL_ESDHC
diff --git a/include/configs/colibri_imx7_emmc.h b/include/configs/colibri_imx7_emmc.h
index 957d420..642da95 100644
--- a/include/configs/colibri_imx7_emmc.h
+++ b/include/configs/colibri_imx7_emmc.h
@@ -125,7 +125,7 @@
 	NFS_BOOTCMD \
 	SD_BOOTCMD \
 	"boot_file=zImage\0" \
-	"console=ttymxc0\0" \
+	"console=ttymxc2\0" \
 	"defargs=\0" \
 	"fdt_board=eval-v3\0" \
 	"fdt_fixup=;\0" \

I’ve just realized that I have to also modify the device tree for U-Boot to change the serial port.

Now the serial port is changed in U-Boot and Linux kernel correctly.

BTW:

  1. Is my changes in device-tree sane and valid?
  2. I wonder if changes in colibri_imx7.c is actually necessary.

Here is the full changes:

diff --git a/arch/arm/dts/imx7-colibri.dts b/arch/arm/dts/imx7-colibri.dts
index cbef5d5..3f5d106 100644
--- a/arch/arm/dts/imx7-colibri.dts
+++ b/arch/arm/dts/imx7-colibri.dts
@@ -13,7 +13,7 @@
 	compatible = "toradex,imx7-colibri", "fsl,imx7";
 
 	chosen {
-		stdout-path = &uart1;
+		stdout-path = &uart3;
 	};
 };
 
@@ -40,10 +40,9 @@
 	status = "okay";
 };
 
-&uart1 {
+&uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_ctrl1>;
-	uart-has-rtscts;
+	pinctrl-0 = <&pinctrl_uart3>;
 	fsl,dte-mode;
 	status = "okay";
 };
@@ -63,19 +62,10 @@
 		>;
 	};
 
-	pinctrl_uart1: uart1-grp {
+	pinctrl_uart3: uart1-grp {
 		fsl,pins = <
-			MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX	0x79
-			MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX	0x79
-			MX7D_PAD_SAI2_TX_BCLK__UART1_DTE_CTS	0x79
-			MX7D_PAD_SAI2_TX_SYNC__UART1_DTE_RTS	0x79
-		>;
-	};
-
-	pinctrl_uart1_ctrl1: uart1-ctrl1-grp {
-		fsl,pins = <
-			MX7D_PAD_SD2_DATA1__GPIO5_IO15		0x14 /* DCD */
-			MX7D_PAD_SD2_DATA0__GPIO5_IO14		0x14 /* DTR */
+			MX7D_PAD_UART3_TX_DATA__UART3_DTE_RX	0x79
+			MX7D_PAD_UART3_RX_DATA__UART3_DTE_TX	0x79
 		>;
 	};
 };
diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c
index a8d8dbd..5f71967 100644
--- a/board/toradex/colibri_imx7/colibri_imx7.c
+++ b/board/toradex/colibri_imx7/colibri_imx7.c
@@ -59,11 +59,9 @@ int dram_init(void)
 	return 0;
 }
 
-static iomux_v3_cfg_t const uart1_pads[] = {
-	MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
-	MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
-	MX7D_PAD_SAI2_TX_BCLK__UART1_DTE_CTS | MUX_PAD_CTRL(UART_PAD_CTRL),
-	MX7D_PAD_SAI2_TX_SYNC__UART1_DTE_RTS | MUX_PAD_CTRL(UART_PAD_CTRL),
+static iomux_v3_cfg_t const uart3_pads[] = {
+	MX7D_PAD_UART3_RX_DATA__UART3_DTE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX7D_PAD_UART3_TX_DATA__UART3_DTE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
 };
 
 static iomux_v3_cfg_t const usdhc1_pads[] = {
@@ -208,7 +206,7 @@ static void setup_iomux_fec(void)
 
 static void setup_iomux_uart(void)
 {
-	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+	imx_iomux_v3_setup_multiple_pads(uart3_pads, ARRAY_SIZE(uart3_pads));
 }
 
 #ifdef CONFIG_FSL_ESDHC
diff --git a/include/configs/colibri_imx7_emmc.h b/include/configs/colibri_imx7_emmc.h
index 957d420..642da95 100644
--- a/include/configs/colibri_imx7_emmc.h
+++ b/include/configs/colibri_imx7_emmc.h
@@ -125,7 +125,7 @@
 	NFS_BOOTCMD \
 	SD_BOOTCMD \
 	"boot_file=zImage\0" \
-	"console=ttymxc0\0" \
+	"console=ttymxc2\0" \
 	"defargs=\0" \
 	"fdt_board=eval-v3\0" \
 	"fdt_fixup=;\0" \

Our default U-Boot configuration enables pinctrl for i.MX 7 which takes pinmux from the device tree. So I think muxing in the board file is not strictly necessary. We left it in for debugging purpose (e.g. when disabling pinctrl configuration).

What is not handled by device tree yet is clocking, but it seems that arch/arm/cpu/armv7/mx7/clock.c:init_clk_uart actually configures all UARTs already.

Since changing console is rather often used I will add UART2/3 to our default device tree. It should then really only be a change of stdout-path in arch/arm/dts/imx7-colibri.dts/and the console= change.