3.2.2.14. MMCSD

3.2.2.14.1. Introduction

The multimedia card secure digital (MMCSD) host controller provides an interface between a local host (LH) such as a microprocessor unit (MPU) or digital signal processor (DSP) and either embedded multimedia card (eMMC), secure digital (SD), or secure digital input/output (SDIO) devices. The MMCSD host controller handles MMCSD and SDIO protocol with minimal LH intervention.

The following image shows the MMCSD Driver Architecture:

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

3.2.2.14.2. References

  1. JEDEC eMMC homepage

  2. SD organization homepage

3.2.2.14.3. Features

The MMCSD 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.14.4. Supported ultra high speed (UHS) 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.14.5. Driver configuration

The default kernel configuration enables support for MMCSD 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 AM62LX.

  • 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.14.6. MMC support in Linux

There is no missing MMC support for AM62LX device.

3.2.2.14.7. 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 that 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.14.8. Listing MMC devices from Linux

eMMC and SD cards register with the MMC subsystem and are available as a block device as /dev/mmcblkn. To find the device index n corresponding to an 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 check existing or mounted disk partitions for an eMMC device, use the command lsblk, such as:

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 formatted disk partitions, usually to virtual file allocation table (vfat) or fourth extended file system (ext4) types.

3.2.2.14.9. Create partitions in eMMC UDA

In eMMC, the user data area (UDA) HW partition is the primary storage space generally used to flash the root filesystem (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 previous example, eMMC is fdisk /dev/mmcblk0.

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

Erase eMMC UDA

In Linux, before creating disk partitions, we can optionally erase eMMC UDA by 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 to the following formula: count = total size UDA (bytes) / bs.

3.2.2.14.9.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 boot loader 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 might not boot from this partition if bootable flag is not set.

3.2.2.14.9.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.14.10. Formatting eMMC partitions from Linux

After creating a partition/s, the partition can be formatted 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.14.10.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.14.10.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.14.11. Flash eMMC for MMCSD boot

In this example, we show one simple method for flashing to eMMC for MMCSD boot from eMMC UDA in filesystem (FS) mode. Know this is not the only method for flashing the eMMC for this boot mode.

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

3.2.2.14.11.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 by 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 boot loader 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.14.11.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 by 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 tar file) 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 tar file

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/*