Xavier NX SDMMC1 and SD Card Booting

tegrabl_error_t tegrabl_sd_get_platform_params(uint32_t *instance, struct tegrabl_sd_platform_params *params)
{
	uint32_t i;
	int32_t offset;
	void *fdt = NULL;
	tegrabl_error_t err = TEGRABL_NO_ERROR;
	const char *temp;
	const uint32_t *data;
	int32_t len;
	const char *name;

	err = tegrabl_dt_get_fdt_handle(TEGRABL_DT_BL, &fdt);
	if (err != TEGRABL_NO_ERROR) {
		pr_error("Failed to get bl-dtb handle\n");
		goto fail;
	}

	err = TEGRABL_ERROR(TEGRABL_ERR_NOT_FOUND, 0);
	for (i = 0; i < ARRAY_SIZE(sdmmc_nodes); i++) {
		name = fdt_get_alias(fdt, sdmmc_nodes[i]);
		pr_info("!!!!!!!!SDMMC Name: %s\n", name);
		if (name == NULL) {
			continue;
		}
		offset = fdt_path_offset(fdt, name);
		pr_info("!!!!!!!!SDMMC offset: %d\n", offset);
		if (offset < 0) {
			err = TEGRABL_ERROR(TEGRABL_ERR_NOT_FOUND, 1);
			pr_error("Error while finding sdmmc node\n");
			goto fail;
		}

		/* if node does not have status=ok, skip then try next node */
		temp = fdt_getprop(fdt, offset, "status", NULL);
		//pr_info("!!!!!!!!SDMMC Status: %s\n", temp);
		if (temp != NULL) {
			pr_info("sdmmc node status = %s\n", temp);
			if (strcmp(temp, "okay")) {
				pr_info("sdmmc node status is disabled\n");
				continue;
			}
		}

		/* if node has property named non-removable, skip then try next node */
		temp = fdt_getprop(fdt, offset, "non-removable", NULL);
		if (temp != NULL) {
			pr_info("sdmmc node is non-removable\n");
			continue;
		}

		*instance = i;
		pr_info("sdcard instance = %d\n", i);

		data = fdt_getprop(fdt, offset, "cd-gpios", &len);
		if ((data == NULL) || (len < 0))
			continue;

		if (len != 12)
			continue;

		params->cd_gpio.handle = fdt32_to_cpu(data[0]);
		params->cd_gpio.pin = fdt32_to_cpu(data[1]);
		params->cd_gpio.flags = fdt32_to_cpu(data[2]);
		pr_info("sdcard gpio handle 0x%x\n", params->cd_gpio.handle);
		pr_info("sdcard gpio pin 0x%x\n", params->cd_gpio.pin);
		pr_info("sdcard gpio flags 0x%x\n", params->cd_gpio.flags);

		data = fdt_getprop(fdt, offset, "vmmc-supply", NULL);
		if (data != NULL) {
			params->vmmc_supply = fdt32_to_cpu(*data);
			pr_trace("vmmc-supply 0x%x\n", params->vmmc_supply);
		} else {
			params->vmmc_supply = 0;
			pr_error("no regulator info present for vmmc-supply\n");
			return TEGRABL_ERROR(TEGRABL_ERR_INVALID_CONFIG, 0);
		}
		err = TEGRABL_NO_ERROR;
		if (i == 1) {
			break;
		}
	}

fail:
	return err;
}

I modified the following function to not break from the loop after i=0 but now it seg faults when the loop continues.

Also I am using Jetpack 4.4.1 and CBoot 32.4.4

The other function that seems to point to a problem is sd_bdev_is_card_present. When the tegrabl_sd_get_platform_params function returns the first sdhci@3400000 and instance 0, the sd_bdev_is_card_present function prints “No sdcard” and it checks if it is present with the following line:

	*is_present = (pin_state == GPIO_PIN_STATE_HIGH) ^ is_active_low;

After it runs tegrabl_sd_get_platform_params it continues to try and open the block device on sdhci@3400000. It does this in tegrabl_blockdev_open. This function gets the block device ID from the instance number, which I have tried changing. After it gets the block device it loops over entry in the list of block devices and if the entry matches a device ID then it opens that blockdev. What seems to be happening is that there are three entries in this blockdev list and none of the device ID’s match so it always exits early and can’t boot from the sd card.

The way it gets the device ID is the following:

#define TEGRABL_BLOCK_DEVICE_ID(storage_type, instance) \
	((storage_type) << 16 | (instance))

So if sd_bdev_is_card_present set is_present to true then it would add that block device to the block device list that tegrabl_blockdev_open. This means the problem definitely stems from what I posted two posts ago.

sd_read_pin_status is what sets the pin_state

The hardware pin starts from 1 so sdmmc1 is mapping to instance 0. Which means sdmmc3 is mapping to 2. Not 3.

Also, sdhci@3400000 is the sdmmc1 controller. Thus, sdhci@34400000 is the one we need.

You can try my patch here. Though I don’t have device to validate. This may be better than hacking the 0 to 2.

diff --git a/lib/linuxboot/removable_boot.c b/lib/linuxboot/removable_boot.c
index adc81ef..5e39d59 100644
--- a/lib/linuxboot/removable_boot.c
+++ b/lib/linuxboot/removable_boot.c
@@ -28,6 +28,8 @@
 #include <extlinux_boot.h>
 #endif
 #include <removable_boot.h>
+#include <tegrabl_sd_param.h>
+#include <tegrabl_sd_pdata.h>
 
 static tegrabl_error_t load_from_partition(struct tegrabl_fm_handle *fm_handle,
 										   void **boot_img_load_addr,
@@ -95,11 +97,14 @@
 	struct tegrabl_bdev *bdev = NULL;
 	struct tegrabl_fm_handle *fm_handle = NULL;
 	tegrabl_error_t err = TEGRABL_NO_ERROR;
+	struct tegrabl_sd_platform_params sd_params;
+	uint32_t sd_instance = 0;
 
 	/* Get device type */
 	if (boot_type == BOOT_FROM_SD) {
 		boot_type_str = "SD";
 		device_type = TEGRABL_STORAGE_SDCARD;
+		tegrabl_sd_get_platform_params(&sd_instance, &sd_params);
 	} else if (boot_type == BOOT_FROM_USB) {
 		boot_type_str = "USB";
 		device_type = TEGRABL_STORAGE_USB_MS;
@@ -128,7 +133,11 @@
 	}
 
 	/* Publish partitions of storage device*/
-	bdev = tegrabl_blockdev_open(device_type, device_instance);
+	if(boot_type != BOOT_FROM_SD)
+	    bdev = tegrabl_blockdev_open(device_type, device_instance);
+	else
+	    bdev = tegrabl_blockdev_open(device_type, sd_instance);
+
 	if (bdev == NULL) {
 		err = TEGRABL_ERROR(TEGRABL_ERR_OPEN_FAILED, 0);
 		goto fail;

I am using CBoot 32.4.4(Jetpack 4.4.1) so won’t be able to use this exact diff. Also, I dont think cboot is even finding the sdmmc3 controller

Then please move to rel-32.5.1 or rel-32.6.1.

Can I use a newer CBoot with an older Jetpack version? I have to use Jetpack 4.4.1 for some userspace software

You can try, but no guarantee for the compatibility.

Would you be able to help me find the same codepath in CBoot 32.4.4? I appreciate the help and I think my previous posts should give an idea of the places I have been looking

Probably this one. I don’t check either. You can try to add some log to check.

partner/common/lib/linuxboot/usb_sd_boot.c

Hi Wayne,

NX has both emmc and sd card variant and cboot support boot from both emmc and sd card.
If it is sdcard, this this controller is used
mmc0: SDHCI controller on 3400000.sdhci [3400000.sdhci] using ADMA 64-bit with 64 bit addr

If it is emmc then this controller is used
[ 5.109436] mmc0: SDHCI controller on 3460000.sdhci [3460000.sdhci] using ADMA 64-bit with 64 bit addr

during boot, based on the module eeprom id we disable one or the other sdhci node

            fragement-tegra-sdhci-sd-dis {
                    ids = ">=3668-0001-000";
                    override@0 {
                            target = <&sdhci_sd>;
                            _overlay_ {
                                    status = "disabled";
                            };
                    };
            };

            fragement-tegra-sdhci-emmc-dis {
                    ids = ">=3668-0000-000";
                    override@0 {
                            target = <&sdhci_emmc>;
                            _overlay_ {
                                    status = "disabled";
                            };
                    };
            };

So, I don’t think, customer has to do anything in cboot.
they just need to make sure that they are using the right controller and its available in the SODIM connector. Please check the schematic to see of both the emmc and sd pins are coming out of sodimm connector and not disable the nodes

@Bibek ,

This customer is using extra sdcard slot on sdmmc3 over his emmc module. So its sdcard is not 3400000.sdhci.