Booting from second SD card on Jetson Tx2i

Hey folks,

Having a bit of trouble booting from the second SD card on the Jetson Tx2i during Uboot and wondering what exactly needs to be updated in the code for it to work correctly. I can successfully boot from the first SD card, but not from the second. Even weirder though, if I boot into the kernel, then reboot, then try to boot from the second SD card, it works. So the kernel is doing something that persisting through a reboot that allows me to boot from the second SD card… I can post the kernel patches I made if required, but ultimately this should be solvable without seeing that I think.

Here’s what I’ve done…

  • I have the latest uboot branch from git://nv-tegra.nvidia.com/3rdparty/u-boot.git
  • I’ve added sdhci@3440000 to tegra186-p2771-0000.dtsi
+       sdhci2 = "/sdhci@3440000";  /* under aliases */
+	sdhci@3440000 {
+		status = "okay";
+ 		bus-width = <4>;
+ 	};
  • I’ve add sdhci@3440000 to tegra186.dtsi which was basically a copy of the definition of sdhci@3400000
+	sdhci@3440000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03440000 0x0 0x200>;
+		resets = <&bpmp TEGRA186_RESET_SDMMC3>;
+		reset-names = "sdhci";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC3>;
+		interrupts = <GIC_SPI 64 0x04>;
+		status = "disabled";
+	};

I’ve finally removed sdchi@3400000 from tegra186-p2771-0000-500.dts so that I can power the card manually.

-	sdhci@3400000 {
-		cd-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_LOW>;
-		power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
-	};
-

This results in a ‘Card did not respond to voltage select!’ error during uboot as the SPI has a timeout error.
There’s an obvious thing that worries me, which is that there’s no autocal routine defined for the Tegra186 despite being detailed in the TRM (the routine is defined for the Tegra210 and Tegra30 in board2.c though). Does this need to be implemented for the card to respond?
Secondly, there appears to be a dedicated SD power pin for the ‘original’ SD pins (SDCARD_PWR_EN on H16), but no dedicated pin for SDIO. I just used GPIO0_CAM_PWR on G8 for that. Perhaps this is wrong, but the kernel handles it ok.

Additional info. I’ve also added this to uboot environment to allow booting from cards.

set boot_targets 'mmc1 mmc2 mmc0 usb0 pxe dhcp'
set bootcmd_mmc0 'setenv devnum 0; gpio clear p6; gpio clear r0; sleep 1; setenv rootfs /dev/mmcblk0p1; run cbootargs_set; run mmc_boot'
set bootcmd_mmc1 'setenv devnum 1; gpio clear r0; gpio set p6; sleep 1; setenv rootfs /dev/mmcblk2p1; run cbootargs_set; run mmc_boot'
set bootcmd_mmc2 'setenv devnum 2; gpio clear p6; gpio set r0; sleep 1; setenv rootfs /dev/mmcblk1p1; run cbootargs_set; run mmc_boot'

set cbootargs_common ' rootwait rw rootfstype=ext4 console=ttyS2,115200n8 console=tty2 fbcon=map:0 net.ifnames=0 video=tegrafb no_console_suspend=1 earlycon=uart8250,mmio32,0xc280000 nvdumper_reserved=0x2372e0000 gpt usbcore.old_scheme_first=1 tegraid=18.1.2.0.0 maxcpus=6 boot.slot_suffix= boot.ratchetvalues=0.2031647.1 bl_prof_dataptr=0x10000@0x235840000 sdhci_tegra.en_boot_part_access=1'

set cbootargs_set 'set cbootargs root=${rootfs}${cbootargs_common}'

Sorry that I don’t get your problem here. Generally you don’t need to modify device tree for booting from external media.

Are you trying to add a new sdcard slot on your board?

The Jetson Tx2i added SDIO lines to allow for a second SD card. My custom board has two SD card slots so I added the definitions for that second card in the device trees in both the kernel and in uboot - i.e. there was no reference to sdhci@3440000 in the stock kernels provided by the SDK, so I added it.
If I don’t add those definitions to the device trees, the second SD card is not enumerated.

Unfortunately I’m still stuck on this. I hope my problem is clear now, but just to summarise…

  1. The Jetson Tx2i added support for a second SD card at the connector (e.g. see Jetson TX2 / TX2i System-on-Module document, section 4)
  2. My carrier board has two SD card slots, one for the SDMMC1 interface at 3400000, and the other for the SDMMC3 at 3440000 (can be found at e.g. Tegra X2 (Parker Series SoC) Technical Reference Manual, table 412)
  3. The latest u-boot found at git://nv-tegra.nvidia.com/3rdparty/u-boot.git does not contain sdhci@3440000 in the tegra186 device tree, but does contain sdhci@3400000
  4. I added it via the steps in the OP
  5. Both SD cards I'm using contain a rootfs which I'm using to boot Linux from
  6. Only the SDMMC1 interface seems to work, the other interface has a 'Card does not respond to voltage select!' error.

What other changes are required in u-boot for this to work?

Usually, there are separate clock sources that need to be enabled for additional controllers.

First, search through the U-Boot source and see if you can find where the SDMMC1 clocks get initialized. You might be able to easily see the missing clock enable for SDMMC3 and add it along with the clock enable for SDMMC1. Second, search for the SDMMC1 and SDMMC3 clock enable in the kernel. Since SDMMC3 appears to be working for you in the kernel it probably has all of the clocks properly enabled for each of the controllers. bpmp TEGRA186_CLK_SDMMC3 in the DT indicates there is a required clock for the SDMMC3 controller. Next, do a deep dive into the TRM and read Chapter 4 on the Clock Controller and Chapter 36 on the SD/MMC controller to see if you can find the required clock for the SDMMC3 interface. Finally, make sure all of the appropriate pad and I/O control logic for the SDMMC3 in the kernel has been replicated into the U-Boot code.

Sorry, my response is so generic. I can’t give you any more help without doing the work for you. :-)

Thanks for the reply, I’ll have a look through to see where and when clocks are getting initialised to see if that solves it. the U-boot initialisation process for the sd cards is definitely a lot more involved in the kernel, however it seems to work ok for SDMMC1 in u-boot, so I assume it’s just a missing initialisation somewhere specific to SDMMC3 that’s missing.

Solution ended up being fairly simple. You need to turn on the MAX7720024 LDO5. In p2771-0000.c within uboot this is only done for SDMMC1. Below was what I added and works fine now.

val = 0xF2;
ret = dm_i2c_write(dev, MAX77620_CNFG1_L5_REG, &val, 1);
if (ret) {
	printf("LD5 write failed: %d\n", ret);
	return ret;
}