Disable and Enable eMMC

Hi Folks -

Bit of a different “disable eMMC” question than the ones I have seen so far. My apologies if it is a duplicate and thank you in advance for your help.

We are trying to power down the internal eMMC after boot. The eMMC has a 3v3 rail and a 1v8 rail. The 3v3 rail isn’t used by any other component so it should be possible to turn it off, right? We edited the device-tree to remove the “non-removable” flag from the sdhci@3460000 and then did

echo 0 > /sys/kernel/debug/3460000.sdhci/card_insert

This set off an immediate kernel panic. Snips of the stack trace are below.

[ 293.684746] Unable to handle kernel NULL pointer dereference at virtual address 0000001c
[ 293.684924] Mem abort info:
[ 293.684979] ESR = 0x96000005
[ 293.685036] Exception class = DABT (current EL), IL = 32 bits
[ 293.685140] SET = 0, FnV = 0
[ 293.685195] EA = 0, S1PTW = 0
[ 293.685250] Data abort info:
[ 293.685343] ISV = 0, ISS = 0x00000005
[ 293.685410] CM = 0, WnR = 0
[ 293.685473] user pgtable: 4k pages, 39-bit VAs, pgd = ffffffc1857d4000
[ 293.685586] [000000000000001c] *pgd=0000000000000000, *pud=0000000000000000
[ 293.685720] Internal error: Oops: 96000005 [#1] PREEMPT SMP
[ 293.685819] Modules linked in: spidev zram overlay nvgpu bluedroid_pm ip_tables x_tables
[ 293.686005] CPU: 0 PID: 1645 Comm: kworker/0:3 Not tainted 4.9.140-tegra #62
[ 293.686182] Hardware name: Jetson-AGX (DT)
[ 293.686527] Workqueue: events_freezable mmc_rescan
[ 293.686895] task: ffffffc7d5561c00 task.stack: ffffffc7d52b8000
[ 293.687356] PC is at blk_free_tags+0x24/0x88
[ 293.687680] LR is at mmc_cmdq_clean+0x30/0xa8
[ 293.688631] pc : [] lr : [] pstate: 80c00045
[ 293.695981] sp : ffffffc7d52bbaf0
[ 293.699136] x29: ffffffc7d52bbaf0 x28: 0000000000000000
<… snip …>
[ 247.472722] Process kworker/1:4 (pid: 1879, stack limit = 0xffffffc7d3cdc000)
[ 247.479631] Call trace:
[ 247.482261] [] blk_free_tags+0x24/0x88
[ 247.487073] [] mmc_cmdq_clean+0x30/0xa8
[ 247.492151] [] mmc_blk_remove_req.part.13+0x78/0xd0
[ 247.498530] [] mmc_blk_remove_parts.isra.14+0x70/0x98
[ 247.504743] [] mmc_blk_remove+0x2c/0x198
[ 247.509992] [] mmc_bus_remove+0x68/0x78
[ 247.514809] [] __device_release_driver+0x9c/0x118
[ 247.520755] [] device_release_driver+0x2c/0x40
[ 247.526097] [] bus_remove_device+0xec/0x190
[ 247.531436] [] device_del+0x110/0x248
[ 247.536594] [] mmc_remove_card+0x54/0x98
[ 247.542105] [] mmc_remove+0x28/0x40
[ 247.547004] [] mmc_detect+0x4c/0x90
[ 247.552081] [] mmc_rescan+0xc0/0x370
[ 247.557251] [] process_one_work+0x1e4/0x4b0
[ 247.562672] [] worker_thread+0x50/0x4c8
[ 247.568443] [] kthread+0xec/0xf0
[ 247.573255] [] ret_from_fork+0x10/0x30
[ 247.578514] —[ end trace beeaea93140524dc ]—

So, this didn’t work so much. Does anyone have any advice on how to safely and cleanly power down the eMMC after boot?

Thanks very much!

Hi,

What is the purpose to do this to emmc? You are using emmc to boot up, right?

We are using the eMMC to boot – is there any other way to boot the device? Perhaps we could explore that as well…

We have seen some problems in our application which might be reduced if we could turn off power to the eMMC. I’m not allowed to say more, but it would be great if we could actually disable the 3v3 power supply after we’ve booted the device.

In our recent efforts, we’ve executed the code in sdhci-tegra.c:

regulator_disable(host->mmc->supply.vmmc);

But there appears to be no effect when we check the debugfs:

root@xavier:/sys/kernel/debug/regulator/vddio-emmc-3v3/regulator# cat microvolts 
3300000
root@xavier:/sys/kernel/debug/regulator/vddio-emmc-3v3/regulator# cat state
enabled

Any help appreciated!

Hi,

I don’t think we support to remove the power of emmc. I mean the request sounds not reasonable that you want to disable emmc but you are also booting from emmc…
Such case never happened before.

This has definitely been done before I. The greater Linux/Ubuntu universe — We are modeling our efforts on LiveCD and USB Stick based Linux distributions that disable the boot device after boot is complete.

I understand that it may not have been done before with Jetson Xavier and may not be supported. But maybe you can tell me if the enable for ldo3 is wired up to be actuated? If it is wired up, does the bpmp api actually support actuating the enable?

Thanks!

Hi,

Is this a custom carrier board? If so, are you sure this board is using a gpio on regulator?

You can just disable/enable the regulator through sysfs.

Standard development carrier.

The regulator in question is on the SoM itself tied to the eMMC, so I don’t have access to it.

The only reference we can find to the regulator is in the debugfs at /sys/kernel/debug/regulator and nothing we have tried has succeeded in changing anything. It could be we have been trying the wrong things, suggestions are welcome!

(My phone keeps correcting the text: there may be typos and pathnames are from memory. Apologies for errors.)

I suspect these have created a ramdisk and performed a pivot_root to the ramdisk. I have no idea what issues you would run into disabling eMMC (no doubt lots of issues), but prior to trying to power down eMMC, did you provide another filesystem?

Yes - we created a ramdisk and performed a pivot_root – exactly as you say. Nice!

We have also run off a solid state drive filesystem.

In both cases, we can run without the eMMC mounted. In neither case have we been able to power down the eMMC.

We can execute the regulator_disable function but we don’t see any effect. Either the BPMP api doesn’t support disabling this regulator or the hardware enable is not physically wired up to a GPIO or we are looking for an effect in the wrong places.

Thanks for helping, your advice is welcome!

Unfortunately I do not know what else looks at eMMC. Without this being mounted the driver would still see the disk, and apps such as “lsblk” would be able to see the drive’s partitions. I have no idea how to do it, but you may have to find some way to make the drive “invisible” to programs like “lsblk” and “gdisk” before cutting power. The filesystem on the disk is not in use, now you have to find a way to remove the drivers for the disk from seeing and interpreting the eMMC as partitions. The implication is that no more of the “/dev/mmcblk0*” will exist (the drivers seeing the device are why those files exist since they are pseudo files and not real files…if the driver has been properly prevented from seeing the hardware, then the device special files will disappear).

I suppose that if there is also an SD card, then there might be some problems with trying to re-enumerate the SD card as mmcblk0 once the original mmcblk0 is gone (the SD card would have been mmcblk1).

You are correct, there is also the problem of disconnecting the driver. We have followed up the call-trace above and it definitely does not like the “device_del” call. That call requires on the device having been added with “device_add” which is appropriate for removable devices. As a built in device-tree device, I suspect that “device_add” was not used for initial configuration.

However, I think that problem is “just a linux problem.” I do not mean to minimize that problem, but we should be able to reconfigure the kernel & device tree to treat the eMMC as removable, just like an SDcard or the LiveCD//USBStick boot methods.

I don’t think when devices are added/removed that existing devices are re-enumerated. mmcblk1 would stay as is.

Of course there is no point in doing that if we can’t power down the eMMC.

Thus the drivers are still running when the hardware is yanked away from them. Non-hot-plug hardware is being yanked without the driver knowing the hardware is no longer there. Removing the drivers will only work if they are in module format, and although some parts can be module format, it is very unlikely that all parts can be a module. Even if these are modules, you would need a way to tell the module to cease using the hardware prior to an rmmod. If you have such a method to tell the driver to cease using the hardware, then you don’t need a module format anyway.

I think you are correct about there being “some way” to make the eMMC removable, but someone familiar with eMMC setup and tuning in early boot stages would probably be the only one able to give any meaningful comments on the topic (and that isn’t me).

@linuxdev, totally agree. The eMMC driver – shdci-tegra – is a kernel built-in. We briefly tried to load the sdhci-tegra as a module to allow us to rmmod it later, but that fell over immediately. That failed to boot and we didn’t even bother trying to figure out why since that path doesn’t really make sense. The very first thing the kernel needs to have is the filesystem and therefore the eMMC driver. It can’t even load initrd if it can’t read the disk, nor can it find any modules.

So what we would need to do is invoke the same functions that enable removability, and configure it correctly from the get go, while keeping the eMMC as a built in module.

That’s a pretty tall ask, and one we won’t work further on unless we learn that we can in fact turn off the power to the eMMC. So far, I suspect the BPMP API does not actually let us to disable that regulator.

Thanks for your interest! I very much appreciate the chance to “talk” through these issues.

I have to wonder if suspend to RAM either turns off eMMC power, or reduces it some? If you were to customize this, then I suspect borrowing from suspend to RAM (a modification, not direct use) would be the place to start.

I am looking through the S2RAM infrastructure and all signs suggest that the Xavier only supports “Suspend to Idle” in the default tegra build (4.9.140-tegra). In /sys/power/state we find freeze and mem but there is no mem_sleep file to list the available suspend end points. So while a promising avenue to pursue, this seems like it doesn’t go where we want.

Will keep you posted if I learn about the power enable.