Unable to set GPIO HIGH during u-boot (gpio DD0 not reserved)

Hello,

Could someone give me some direction on how I can set a GPIO pin HIGH during boot, before the kernel is loaded. We designed a custom carrier board for the Jetson Nano Production Module, the main power supply enable on the carrier board is connected to pin GPIO3_PDD.00, the enable pin needs to be high for the power supply to be active.

The SoM is running L4T 32.7.2

I read the Bring Up and Adaptation Doc to try to accomplish this but no luck.
Thus far I have exported the customized pinmux excel sheet where I set GPIO3_PDD.00 to an output and set initial state to “Drive 1”.

I then replaced the following two files with the files I exported from the sheet:

Linux_for_Tegra/source/public/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-porg-gpio-p3448-0002-b00.dtsi

Linux_for_Tegra/source/public/hardware/nvidia/platform/t210/porg/kernel-dts/porg-platforms/tegra210-porg-pinmux-p3448-0002-b00.dtsi

using the following command I compiled the dts files:

cd source/public/kernel/kernel-4.9/
sudo make ARCH=arm64 dtbs
sudo make CROSS_COMPILE=$HOME/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm64 dtbs

Then I copied the following file to L4T dir:

cp source/public/kernel/kernel-4.9/arch/arm64/boot/dts/tegra210-p3448-0002-p3449-0000-b00.dtb ./kernel/dtb/tegra210-p3448-0002-p3449-0000-b00.dtb

Then I used the following command to flash the new dtb:

sudo ./flash.sh -k DTB jetson-nano-emmc mmcblk0p1

Before flashing I decompiled the the new device tree and I confirmed that the pin I want GPIO3_PDD.00 is set to high:
I can see that pin 0xe8 is now in “gpio-output-high”

  default {
  	gpio-input = <0x0c 0x0d 0x0e 0x0f 0x22 0x05 0xbc 0xbd 0xbe 0xc1 0xc2 0xa8 0xa9 0x4d 0x14 0x3a 0x3d 0x3f 0x41>;
  	gpio-output-low = <0xcb 0x38 0x3b 0x3c 0x40 0x42>;
  	gpio-output-high = <0xe8 0x06 0xbb 0xe7>;
  	linux,phandle = <0x41>;
  	phandle = <0x41>;
  };

Which is great because now after the system boots the systems stays on, but the pin only goes high after the kernel is loaded. This takes around 8 seconds, which is way too long. Is there a way to drive GPIO3_PDD.00 pin high before the kernel is loaded? I tried to recompile u-boot, but the resulting device tree does not have a gpio defaults section is it.

Since cboot source is not available u-boot seems like the place were I should try set the pin high.

I added the following code to “/Linux_for_Tegra/source/public/u-boot/board/nvidia/p3450-0000/p3450-0000.c”

#include <asm/gpio.h>

void pin_mux_mmc(void)
{
struct udevice *dev;
uchar val;
int ret;
printf(“Setting Power EN pin HIGH \n”);
gpio_request(TEGRA_GPIO(DD, 0), “Power EN”);
gpio_direction_output(TEGRA_GPIO(DD, 0), 1);

to compile and flash u-boot I ran the following commands.
from “/Linux_for_Tegra/source/public/u-boot"

sudo make distclean
sudo make p3450-0000_defconfig
sudo make CROSS_COMPILE=$HOME/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
sudo cp u-boot{,.bin,.dtb,-dtb.bin} Linux_for_Tegra/bootloader/t210ref/p3450-0000

Then from “/Linux_for_Tegra/"

sudo ./flash.sh jetson-nano-emmc mmcblk0p1

The result of this is the following output from the debug console:

U-Boot 2020.04 (Aug 26 2022 - 00:10:50 -0400)

SoC: tegra210
Model: NVIDIA Jetson Nano Developer Kit
Board: NVIDIA P3450-0000
DRAM: 4 GiB
Setting Power EN pin HIGH
MMC: sdhci@700b0000: 1, sdhci@700b0600: 0
Loading Environment from MMC… OK
In: serial
Out: serial
Err: serial
Net: No ethernet found.
Hit any key to stop autoboot: 0
MMC: no card present
switch to partitions #0, OK
mmc0(part 0) is current device
Scanning mmc 0:1…
Found /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
879 bytes read in 24 ms (35.2 KiB/s)
1: primary kernel
Retrieving file: /boot/initrd
7160179 bytes read in 176 ms (38.8 MiB/s)
Retrieving file: /boot/Image

Still the pin only goes high after the device tree is loaded.
Which is too late…

hello klaskak,

FYI,
here’re approaches for GPIO configuration in u-boot.

  1. modify the pinmux in the DTB to the correct non-SFIO setting to allow the GPIO function
  2. interrupt u-boot, set the pinmux and gpio registers via ‘write 0xNNNNNNNN’ commands
  3. code implementation, for example, on Nano it would be board/nvidia/p3450-0000/p3450-0000.c. please add your GPIO init to ft_board_setup().

Hello Jerry,

Thank you for the reply,

  1. The DTB has been edited to non-SFIO when I compiled u-boot.
    There is no error while trying to set the pin high but the pin remains low.

  2. Could you please provide more detail on how to suggested approach / where I can find more information about this approach?

  3. Moving the function to ft_board_setup() would negate my efforts since that function is run later in the boot process, and one the Device tree is loaded the device tree takes care of setting the pin high. I am trying to set it high as soon as possible after applying power to the board. putting fprint stat statements in each each of the functions in board/nvidia/p3450-0000/p3450-0000.c I found pin_mux_mmc() was the first function to run.

Thank you in advance

hello klaskak,

may I know what’s the actual use-case.
please also note that, the DTB is loaded and used by CBoot on Nano, not UBoot.

for interrupt u-boot, you may setup a serial console, and issue a key while you see… Hit any key to stop autoboot:
then, you may able to use commands to toggle the pin.

The use case:
The carrier board is battery powered, when the power button is pressed the power supply in enabled. The nano needs to latch the power supply by setting GPIO3_PDD.00 HIGH, otherwise when the user releases the power button the power supply is disabled and power gets cut.

Which device tree does cboot load?

Linux_for_Tegra/kernel/dtb/tegra210-p3448-0002-p3449-0000-b00.dtb
has the following:

gpio@6000d000 {
default {
gpio-input = <0x0c 0x0d 0x0e 0x0f 0x22 0x05 0xbc 0xbd 0xbe 0xc1 0xc2 0xa8 0xa9 0x4d 0x14 0x3a 0x3d 0x3f 0x41>;
gpio-output-low = <0xcb 0x38 0x3b 0x3c 0x40 0x42>;
gpio-output-high = <0xe8 0x06 0xbb 0xe7>;
linux,phandle = <0x41>;
phandle = <0x41>;
};

and Linux_for_Tegra/bootloader/t210ref/p3450-0000/u-boot.dtb
has the following:

gpio@6000d000 {
compatible = “nvidia,tegra210-gpio\0nvidia,tegra30-gpio”;
reg = <0x00 0x6000d000 0x00 0x1000>;
interrupts = <0x00 0x20 0x04 0x00 0x21 0x04 0x00 0x22 0x04 0x00 0x23 0x04 0x00 0x37 0x04 0x00 0x57 0x04 0x00 0x59 0x04 0x00 0x7d 0x04>;
#gpio-cells = <0x02>;
gpio-controller;
#interrupt-cells = <0x02>;
interrupt-controller;
phandle = <0x07>;

  default {
  	gpio-output-high = <0x07 0xe8 0x00>;
  };

};

Is there another device tree that I can compile to set the default pin state to high during cboot?

hello klaskak,

there’s also another partition it contains bootloader DTB binary,
for example, it’s tegra210-p3448-0000-p3449-0000-a02.dtb writing to RP1 and also DTB partition.

Thank you Jerry,
I am aware of the DTB that is in its own partition. I was assuming one of the device trees I pointed out above would be written to the partition.

Could you please specify which device tree I have to edit in the source code to set gpio high in cboot. Could you name the path starting from Linux_for_Tegra/…

hello klaskak,

please check your flash messages to confirm the dtb file burning to the target.
after that, please check the file under… $OUT/Linux_for_Tegra/kernel/dtb/

you may have dtc utility to disassembler the dtb file into text file for modification,
for example, $ dtc -I dtb -O dts -o temp.dts tegra210.dtb
then, please convert the DTS into a new DTB file, $ dtc -I dts -O dtb -o output.dtb temp.dts

As mentioned in my initial post I have edited and confirmed the default pin state in the $OUT/Linux_for_Tegra/kernel/dtb/ Device tree…
I have not gotten the chance to check the flash log, will post with more info soon.