How do I use T30 UART3 on Linux

I’m trying to get a 4th Tegra 3 UART to work on Linux on a Colibri T30 on our carrier board.

(UART (Linux) | Toradex Developer Center)

In Windows CE we’re using T30 pins 115 & 117 as a COM4 serial port. Pins 115/117 are GPIOs W.06/W.07 (182/183), which is UART3 RX/TX to NVIDIA. Under CE we call the function SetGPIOAltFn with the GPIO number and Tegra_AltFn0 to configure it to work as a serial port, and set some registry settings.

How do I do the equivalent in Yocto Linux 2.8? And which /dev/tty will it show up as?

My in-house writeup on how I got this to work.

This gets confusing. These (115 & 117) are the pins we use as COM4 on Windows CE. In the T30 pin function table, the Nvidia name is UART3. Toradex uses letter designations instead of numbers, but their UART_C is NOT Nvidia UART3. Yet in kernel code they also use letter designations, and there UARTC = UART3. Focus on the pins and GPIO designations to keep this straight.

I found a table which has possible functions for each of the pins. Following are the definitions for pins 115/117.
arch/arm/mach-tegra/pinmux-t3-tables.c

              NAME    GPIO  VDD   f0     f1     f2   f3     fSafe  io     reg
  PINGROUP(UART3_TXD, PW6, UART, UARTC, RSVD1, GMI, RSVD2, UARTC, INPUT, 0x3174),\
  PINGROUP(UART3_RXD, PW7, UART, UARTC, RSVD1, GMI, RSVD2, UARTC, INPUT, 0x3178),\

In the kernel code, these pins are configured to work as GPIOs. There is no simple kernel .config entry to get them to switch to the UART function we use in CE. You have to modify the source code. There are two different files which need to be modified, following are context diffs of the necessary changes. Note after these changes the kernel name will have a “-dirty” appended to it. You’ll see this in the modules path name and from getting the kernel name via “uname -r”. This is OK, from Yocto Project “this simply means that modifications in the source directory have not been committed.”


*** arch/arm/mach-tegra/board-colibri_t30_ORIGINAL.c 2021-02-25 10:38:03.911409336 -0800

— arch/arm/mach-tegra/board-colibri_t30.c 2021-03-01 11:56:05.149381453 -0800


— 1313,1319 ----

    &tegra_uarta_device, /* Colibri UART_A (formerly FFUART) */
    &tegra_uartd_device, /* Colibri UART_B (formerly BTUART) */
    &tegra_uartb_device, /* Colibri UART_C (formerly STDUART) */
+   &tegra_uartc_device, /* Tegra UART 3 */
};
static struct uart_clk_parent uart_parent_clk[] = {

— 1393,1399 ----

    colibri_t30_uart_pdata.parent_clk_count = ARRAY_SIZE(uart_parent_clk);
    tegra_uarta_device.dev.platform_data = &colibri_t30_uart_pdata;
    tegra_uartb_device.dev.platform_data = &colibri_t30_uart_pdata;
+   tegra_uartc_device.dev.platform_data = &colibri_t30_uart_pdata;
    tegra_uartd_device.dev.platform_data = &colibri_t30_uart_pdata;
/* Register low speed only if it is selected */


*** arch/arm/mach-tegra/board-colibri_t30-pinmux_ORIGINAL.c 2021-02-25 14:57:27.703779342 -0800

— arch/arm/mach-tegra/board-colibri_t30-pinmux.c 2021-03-01 11:58:17.013387635 -0800


— 577,586 —

     DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT),
     DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_CTS_N, GMI, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_RTS_N, GMI, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_RXD, GMI, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_TXD, GMI, NORMAL, NORMAL, INPUT),
     //multiplexed SDMMC3_DAT7
     DEFAULT_PINMUX(ULPI_CLK, SPI1, NORMAL, NORMAL, INPUT),

— 577,586 ----

     DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT),
     DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT),
!    DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, INPUT),
     //multiplexed SDMMC3_DAT7
     DEFAULT_PINMUX(ULPI_CLK, SPI1, NORMAL, NORMAL, INPUT),

By the way this is version 2.8 of the image & kernel. And the serial port shows up as ttyHS2.

Thank you for an detailed update. Unfortunately Linux BSPs 2.8 for T30 does not support UART configuration by Device Tree. So driver modification is required.