3.2.2.16. MMC/SD

3.2.2.16.1. Introduction

The multimedia card high-speed/SDIO (MMC/SDIO) host controller provides an interface between a local host (LH) such as a microprocessor unit (MPU) or digital signal processor (DSP) and either MMC, SD® memory cards, or SDIO cards and handles MMC/SDIO transactions with minimal LH intervention.

The following image shows the MMC/SD Driver Architecture:

../../../../../_images/Mmcsd_Driver.png

3.2.2.16.2. References

  1. JEDEC eMMC homepage

  2. SD organization homepage

3.2.2.16.3. Acronyms & Definitions

Acronym

Definition

MMC

Multimedia Card

HS-MMC

High Speed MMC

SD

Secure Digital

SDHC

SD High Capacity

SDIO

SD Input/Output

3.2.2.16.4. Features

The SD/MMC driver supports the following features:

  • Support ADMA for DMA transfers

  • HS200 speed mode

  • Support for both built-in and module mode

  • ext2/ext3/ext4 file system support

3.2.2.16.5. SD: Supported High Speed Modes

  • SD

Platform

SDR12

SDR25

SDR50

DDR50

SDR104

AM62*

Y

Y

Y

Y

Y

AM62ax

Y

Y

Y

Y

Y

am64x

Y

Y

Y

Y

Y

am62px

Y

Y

Y

Y

Y

am62lx

N

N

N

N

N

  • eMMC

Platform

DDR52

HS200

HS400

AM62*

Y

Y

N

AM62ax

Y

Y

N

am64x

Y

Y

N

am62px

Y

Y

N

am62lx

Y

Y

N

3.2.2.16.6. Driver Configuration

The default kernel configuration enables support for MMC/SD driver as built-in to kernel. TI SDHCI driver is used. Following options need to be configured in Linux Kernel for successfully selecting SDHCI driver for AM62x.

  • Enable SDHCI support (CONFIG_MMC_SDHCI)

Device Drivers -->
   MMC/SD/SDIO card support -->
      <*> Secure Digital Host Controller Interface support
  • Enable SDHCI platform helper (CONFIG_MMC_SDHCI_PLTFM)

Device Drivers -->
   MMC/SD/SDIO card support -->
      Secure Digital Host Controller Interface support -->
         <*> SDHCI platform and OF driver helper
  • Enable SDHCI controller for TI device (CONFIG_MMC_SDHCI_AM654)

Device Drivers -->
   MMC/SD/SDIO card support -->
      <*> Support for the SDHCI Controller in TI's AM654 SOCs

3.2.2.16. Steps for working around SD card issues in Linux

In some cases, failures can be seen while using some SD cards:

  • Kernel fails to enumerate SD, thus failing to mount the root file system. This is the case when kernel hangs during boot with a message similar to the following:

    [    2.563279] Waiting for root device PARTUUID=835b171b-02...
    
  • A lot of SDHCI register dumps logs getting printed continuously:

    [   10.811723] mmc1: Got data interrupt 0x00000002 even though no data operation was in progress.
    [   10.820321] mmc1: sdhci: ============ SDHCI REGISTER DUMP ===========
    [   10.826745] mmc1: sdhci: Sys addr:  0x00000080 | Version:  0x00001004
    [   10.833169] mmc1: sdhci: Blk size:  0x00007200 | Blk cnt:  0x00000080
    [   10.839593] mmc1: sdhci: Argument:  0x00000000 | Trn mode: 0x00000033
    [   10.846016] mmc1: sdhci: Present:   0x01f70000 | Host ctl: 0x0000001f
    [   10.852440] mmc1: sdhci: Power:     0x0000000f | Blk gap:  0x00000080
    [   10.858864] mmc1: sdhci: Wake-up:   0x00000000 | Clock:    0x00000007
    [   10.865287] mmc1: sdhci: Timeout:   0x00000000 | Int stat: 0x00000000
    [   10.871711] mmc1: sdhci: Int enab:  0x03ff008b | Sig enab: 0x03ff008b
    [   10.878134] mmc1: sdhci: ACmd stat: 0x00000000 | Slot int: 0x00000000
    [   10.884557] mmc1: sdhci: Caps:      0x3de8c801 | Caps_1:   0x18002407
    [   10.890981] mmc1: sdhci: Cmd:       0x00000c1a | Max curr: 0x00000000
    [   10.897404] mmc1: sdhci: Resp[0]:   0x00000b00 | Resp[1]:  0x0075cf7f
    [   10.903828] mmc1: sdhci: Resp[2]:   0x32db7900 | Resp[3]:  0x00000900
    [   10.910251] mmc1: sdhci: Host ctl2: 0x0000000b
    [   10.914682] mmc1: sdhci: ADMA Err:  0x00000000 | ADMA Ptr: 0x00000000a2e90200
    

Given below are the list of various workarounds that can be done in the device tree node to get SD card working. The workarounds are ordered from least to most performance impacting.

Note

All the changes mentioned below, are to be done in the MMCSD device tree node corresponding to the SD instance. This is usually the first (index starting from zero) instance.

  1. Restricting to a given speed mode

    By default the kernel driver tries to enumerate an SD card in the highest supported speed mode. Below is the order in which the driver tries to enumerate an SD card:

    • SDR104

    • DDR50

    • SDR50

    • SD HS

    • SD legacy

    The sdhci-caps-mask can be added to the DT node to cap at a specific mode:

    • Limit to DDR50: sdhci-caps-mask = <0x00000003 0x00000000>

    • Limit to SD HS: sdhci-caps-mask = <0x00000007 0x00000000>

    • Limit to SD legacy: sdhci-caps-mask = <0x00000007 0x00200000>

    The following is an example DT node with the added sdhci-caps-mask:

    &sdhci1 {
       /* SD/MMC */
       vmmc-supply = <&vdd_mmc1>;
       vqmmc-supply = <&vdd_sd_dv>;
       pinctrl-names = "default";
       pinctrl-0 = <&main_mmc1_pins_default>;
       ti,driver-strength-ohm = <50>;
       disable-wp;
       sdhci-caps-mask = <0x00000003 0x00000000>; /* Limiting to DDR50 speed mode */
    };
    

    Limiting to SD HS speed mode can also be done by using the property no-1-8-v. This disables switching to 1.8V which is required for UHS speed modes(SDR104, DDR50, SDR50, SDR25, SDR12):

    &sdhci1 {
       /* SD/MMC */
       vmmc-supply = <&vdd_mmc1>;
       vqmmc-supply = <&vdd_sd_dv>;
       pinctrl-names = "default";
       pinctrl-0 = <&main_mmc1_pins_default>;
       ti,driver-strength-ohm = <50>;
       disable-wp;
       no-1-8-v; /* disabling all the UHS modes */
    };
    
  2. Reduce the bus width

    The SD interface supports a bus width of 4. It can be reduced to 1 by changing the bus-width device tree property from 4 to 1.

    diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
    index 7bbfcb158842..2ef974f7206f 100644
    --- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
    +++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
    @@ -424,7 +424,7 @@
       ti,itap-del-sel-sdr12 = <0x0>;
       ti,itap-del-sel-sdr25 = <0x0>;
       ti,clkbuf-sel = <0x7>;
    -     bus-width = <4>;
    +     bus-width = <1>;
    };
    
    sdhci2: mmc@fa20000 {
    

3.2.2.16.6.1. eMMC HS400 support in Linux

eMMC HS400 is not suppported, refer to this table for the list of modes supported in Linux for AM62x SoC.


3.2.2.16.7. Listing MMC devices from Linux

eMMC and SD cards are registered to the MMC subsystem and availiable as a block device as /dev/mmcblkn. To find which device index n corresponds to eMMC device, check which device includes mmcblknboot0 and mmcblknboot1. Here, mmcblk0* is in eMMC.

root@<machine>:~# ls -l /dev/mmcblk*
brw-rw---- 1 root disk 179,  0 Jan  1 00:10 /dev/mmcblk0
brw-rw---- 1 root disk 179, 32 Jan  8  2025 /dev/mmcblk0boot0
brw-rw---- 1 root disk 179, 64 Jan  8  2025 /dev/mmcblk0boot1
brw-rw---- 1 root disk 179,  1 Jan  1 00:14 /dev/mmcblk0p1
crw------- 1 root root 239,  0 Jan  1 00:00 /dev/mmcblk0rpmb
brw-rw---- 1 root disk 179, 96 Jan  8  2025 /dev/mmcblk1
brw-rw---- 1 root disk 179, 97 Jan  1 00:00 /dev/mmcblk1p1
brw-rw---- 1 root disk 179, 98 Jan  8  2025 /dev/mmcblk1p2

The disk partitions for each MMC device are displayed as /dev/mmcblknpx, to see what disk partitions exist for an eMMC device and if they are mounted, use the command lsblk, like so:

root@<machine>:~# lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
mmcblk0      179:0    0 14.8G  0 disk
mmcblk0boot0 179:32   0 31.5M  1 disk
mmcblk0boot1 179:64   0 31.5M  1 disk
mmcblk1      179:96   0 14.8G  0 disk
|-mmcblk1p1  179:97   0  128M  0 part /run/media/boot-mmcblk1p1
`-mmcblk1p2  179:98   0  1.9G  0 part /

Use the mount and umount commands to mount and unmount disk partitions if they are formated, usally to vfat or ext4 types.

3.2.2.16.8. Create partitions in eMMC UDA

In eMMC, the User Data Area (UDA) HW partition is the primary storage space generally used to flash the rootfs. To create disk partitions in UDA, use the fdisk command. For ex: fdisk /dev/mmcblkn in which n is typically 0 or 1. In the example above, eMMC is fdisk /dev/mmcblk0.

For documentation on using fdisk, please go to: fdisk how-to.

Erase eMMC UDA

In Linux, before creating disk partitions, we can optionally erase eMMC UDA using dd command:

root@<machine>:~# umount /dev/mmcblk0*
root@<machine>:~# dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=n

where n should be determined according the the following formula: count = total size UDA (bytes) / bs.

3.2.2.16.8.1. Create “boot” partition

In this example create a “boot” partition of size 400 MiB which can be formatted to vfat type and will store the bootloader binaries.

root@<machine>:~# fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.39.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): n
Partition type
p   primary (0 primary, 0 extended, 4 free)
e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (1-4, default 1):
First sector (2048-31080447, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-31080447, default 31080447): +400M

Created a new partition 1 of type 'Linux' and of size 400 MiB.
Partition #1 contains a vfat signature.

Do you want to remove the signature? [Y]es/[N]o: y

The signature will be removed by a write command.

Command (m for help): a
Selected partition 1
The bootable flag on partition 1 is enabled now.

Command (m for help): t
Selected partition 1
Hex code or alias (type L to list all): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

Command (m for help): w
The partition table has been altered.
[  644.818358]  mmcblk0: p1
Calling ioctl() to re-read partition table.
Syncing disks.

Make sure bootable flag is set for “boot” partition, ROM may not boot from this patitition if bootable flag is not set.

3.2.2.16.8.2. Create “root” partition

In this example create a “root” partition which can be formatted to ext4 type and will store Linux kernel Image, DTB, and the rootfs.

root@<machine>:~# fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.39.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): n
Partition type
p   primary (1 primary, 0 extended, 3 free)
e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (2-4, default 2):
First sector (821248-31080447, default 821248):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (821248-31080447, default 31080447):

Created a new partition 2 of type 'Linux' and of size 14.4 GiB.

Command (m for help): t
Partition number (1,2, default 2): 2
Hex code or alias (type L to list all): 83

Changed type of partition 'Linux' to 'Linux'.

Command (m for help): w
The partition table has been altered.
Syncing disks.

3.2.2.16.9. Formatting eMMC partitions from Linux

After creating a partition/s, the partition can be formated with the mkfs command. For ex: mkfs -t ext4 /dev/mmcblkn where mmcblk{n} is the MMC device with the new disk partitions to format. The general syntax for formatting disk partitions in Linux is:

mkfs.vfat [OPTIONS] TARGET [BLOCKS]
mkfs.ext4 [-c|-l filename] [-b block-size] [-C cluster-size]

3.2.2.16.9.1. Format to vfat

In this example, format the “boot” partition to type vfat.

root@<machine>:~# mkfs.vfat -F 32 -n "boot" /dev/mmcblk0p1

3.2.2.16.9.2. Format to ext4

In this example, format the “root” partition to type ext4.

root@<machine>:~# mkfs.ext4 -L "root" /dev/mmcblk0p2

Verify partitions

Verify setup of mmcblk0p1 and mmcblk0p2 with lsblk command.

root@<machine>:~# lsblk -o name,mountpoint,label,size,uuid
NAME         MOUNTPOINT                LABEL  SIZE UUID
mmcblk0                                      14.8G
|-mmcblk0p1                            boot   400M E4D4-4879
`-mmcblk0p2                            root  14.4G 74d40075-07e4-4bce-9401-6fccef68e934
mmcblk0boot0                                 31.5M
mmcblk0boot1                                 31.5M
mmcblk1                                      29.7G
|-mmcblk1p1  /run/media/boot-mmcblk1p1 boot   128M 681F-55DD
`-mmcblk1p2  /                         root   8.7G ead4c8bb-fa37-4c4d-9ba3-47a1f3824764

3.2.2.16.10. Flash eMMC for MMCSD boot

In this example, we show one simple method for flashing to eMMC for MMCSD boot from eMMC UDA in FS mode. Please know this is not the only method for flashing the eMMC for this bootmode.

This example assumes the current bootmode is MMCSD boot from SD (FS mode)

3.2.2.16.10.1. Flash to eMMC “boot” partition

root@<machine>:~# umount /run/media/*
root@<machine>:~# mkdir /mnt/eboot /mnt/sdboot
root@<machine>:~# mount /dev/mmcblk0p1 /mnt/eboot
root@<machine>:~# mount /dev/mmcblk1p1 /mnt/sdboot

Verify the partitions are mounted to the correct folders using lsblk command in the column labeled MOUNTPOINTS.

root@<machine>:~# lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
mmcblk0      179:0    0 14.8G  0 disk
|-mmcblk0p1  179:1    0  400M  0 part /mnt/eboot
`-mmcblk0p2  179:2    0 14.4G  0 part
mmcblk0boot0 179:32   0 31.5M  1 disk
mmcblk0boot1 179:64   0 31.5M  1 disk
mmcblk1      179:96   0 29.7G  0 disk
|-mmcblk1p1  179:97   0  128M  0 part /mnt/sdboot
`-mmcblk1p2  179:98   0  8.7G  0 part /

Now we can copy bootloader binaries to eMMC and umount the partitions when writes finish.

root@<machine>:~# ls /mnt/sdboot/
tiboot3.bin  tispl.bin       u-boot.img  uEnv.txt
root@<machine>:~# cp /mnt/sdboot/* /mnt/eboot/
root@<machine>:~# sync && umount /mnt/*

3.2.2.16.10.2. Flash to eMMC “root” partition

root@<machine>:~# umount /run/media/*
root@<machine>:~# mkdir /mnt/eroot /mnt/sdroot
root@<machine>:~# mount /dev/mmcblk0p2 /mnt/eroot
[69229.982452] EXT4-fs (mmcblk0p2): mounted filesystem 74d40075-07e4-4bce-9401-6fccef68e934 r/w with ordered data mode. Quota mode: none.
root@<machine>:~# mount /dev/mmcblk1p2 /mnt/sdroot

Verify the partitions are mounted to the correct folders using lsblk command in the column labeled MOUNTPOINTS.

root@<machine>:~# lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
mmcblk0      179:0    0 14.8G  0 disk
|-mmcblk0p1  179:1    0  400M  0 part
`-mmcblk0p2  179:2    0 14.4G  0 part /mnt/eroot
mmcblk0boot0 179:32   0 31.5M  1 disk
mmcblk0boot1 179:64   0 31.5M  1 disk
mmcblk1      179:96   0 29.7G  0 disk
|-mmcblk1p1  179:97   0  128M  0 part
`-mmcblk1p2  179:98   0  8.7G  0 part /mnt/sdroot
                                      /

Now we can copy rootfs to eMMC (either from SD rootfs or from tarball) and umount the partitions when writes finish.

From SD

root@<machine>:~# ls /mnt/sdroot
bin   dev  home  lost+found  mnt  proc       run   srv  tmp  var
boot  etc  lib        media       opt  root  sbin  sys  usr
root@<machine>:~# cp -r -a /mnt/sdroot/* /mnt/eroot
root@<machine>:~# sync
root@<machine>:~# umount /mnt/*
[70154.205154] EXT4-fs (mmcblk0p2): unmounting filesystem 74d40075-07e4-4bce-9401-6fccef68e934.

From tarball

This sections requires for tisdk-base-image-<soc>evm.rootfs.tar.xz to have been previously copied to the SD card rootfs.

root@<machine>:~# ls
tisdk-base-image-<soc>-evm.rootfs.tar.xz
root@<machine>:~# tar -xpf tisdk-base-image-<soc>-evm.rootfs.tar.xz -C /mnt/eroot
root@<machine>:~# sync
root@<machine>:~# umount /mnt/*