Search by Tags

SD/MMC Card (Linux)

 

Article updated at 25 Apr 2019
Compare with Revision




Subscribe for this article updates

SD/MMC cards which use the MMC subsystem are available as block device through /dev/mmcblk{id}. The kernel normally parses the partition table and exports the partitions of the card using the appendix p{x}, e.g. /dev/mmcblk{id}p{x}.

The following bootlog shows the detection of a SDHCI controller:

[    6.861764] sdhci: Secure Digital Host Controller Interface driver
[    6.870575] sdhci: Copyright(c) Pierre Ossman
[    6.877645] sdhci-pltfm: SDHCI platform and OF driver helper
[    6.885949] sdhci_tegra_init+ #####
[    6.892317] sdhci-tegra sdhci-tegra.3: vddio_sdmmc regulator not found: -19.Assuming vddio_sdmmc is not required.
[    6.908111] sdhci-tegra sdhci-tegra.3: vddio_sd_slot regulator not found: -19. Assuming vddio_sd_slot is not required.
[    6.924626] mmc0: Invalid maximum block size, assuming 512 bytes
[    6.933627] mmc0: no vmmc regulator found
[    6.940763] mmc0: SDHCI controller on sdhci-tegra.3 [sdhci-tegra.3] using ADMA
[    6.954955] sdhci_tegra_init- #####

Before inserting any card no interrupts are generated yet:

root@colibri-t20:~# cat /proc/interrupts | grep mmc
 63:          0          0       GIC  mmc0
215:          0          0      GPIO  mmc0

And the IOs debugging information is not valid yet:

root@colibri-t20:~# cat /sys/kernel/debug/mmc0/ios 
clock:          0 Hz
vdd:            0 (invalid)
bus mode:       1 (open drain)
chip select:    0 (don't care)
power mode:     0 (off)
bus width:      0 (1 bits)
timing spec:    0 (legacy)

With the MMC_CD card detection GPIO pin still being pulled-up:

root@colibri-t20:~# cat /sys/kernel/debug/gpio | grep cd
 gpio-23  (sdhci_cd            ) in  hi

SD/MMC Card Insertion

On insertion, the kernel starts scanning the card in order to create devices for each partition. Depending on the Automount configuration the detected file systems get mounted automatically.

[  229.601281] mmc0: host does not support reading read-only switch. assuming write-enable.
[  229.611762] mmc0: new high speed SDHC card at address 0007
[  229.619048] mmcblk0: mmc0:0007 SD8GB 7.42 GiB 
[  229.626557]  mmcblk0: p1

Interrupts are happening (note one card detect GPIO interrupt thereof):

root@colibri-t20:~# cat /proc/interrupts | grep mmc
 63:       1336          0       GIC  mmc0
215:          1          0      GPIO  mmc0

And the IOs debugging information should now show valid information about the inserted card:

root@colibri-t20:~# cat /sys/kernel/debug/mmc0/ios 
clock:          48000000 Hz
vdd:            20 (3.2 ~ 3.3 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      2 (4 bits)
timing spec:    2 (sd high-speed)

With the MMC_CD card detection GPIO pin now being pulled to ground:

root@colibri-t20:~# cat /sys/kernel/debug/gpio | grep cd
 gpio-23  (sdhci_cd            ) in  lo

More specifics about the inserted card can be found in its CID/CSD:

root@colibri-t20:~# cat /sys/bus/mmc/devices/mmc0\:0007/cid 
41343253443847423000066bf800d100
root@colibri-t20:~# cat /sys/bus/mmc/devices/mmc0\:0007/csd
400e00325b5900003b5f7f800a400000

The utility df shows the usage of the SD/MMC card:

root@colibri-t20:~# df | grep mmc
/dev/mmcblk0p1         7766188    434768   7331420   6% /media/733D-4531

And mount shows the mounting status:

root@colibri-t20:~# mount | grep mmc
/dev/mmcblk0p1 on /media/733D-4531 type vfat (rw,nosuid,nodev,relatime,gid=6,fmask=0007,dmask=0007,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro,uhelper=udisks)

From regular SD cards one should be able to read with sustained data rates of around 10 to 20 MB/sec:

root@colibri-t20:~# hdparm -t /dev/mmcblk0

/dev/mmcblk0:
 Timing buffered disk reads:  34 MB in  3.16 seconds =  10.75 MB/sec

SD/MMC Card Removal

Kernel message:

[  988.230735] mmc0: card 0007 removed

Triggered by another card detection interrupt:

root@colibri-t20:~# cat /proc/interrupts | grep mmc
 63:       1340          0       GIC  mmc0
215:          2          0      GPIO  mmc0

UHS-I Support

Note: Please make sure your carrier board does not pull-up any of the MMC, MMC1 or SD1 signals to 3.3 volt (e.g. remove R46 to R54 for 8-bit or R29 to R32 and R39 for 4-bit SD/MMC slot on our Apalis Evaluation Board V1.1A) before attempting to activate this feature.

Activation

Apalis T30 V1.1x

This feature of the Linux SDHCI driver may be activated using the mmc_uhs kernel parameter, which can be set either from within U-Boot or Linux as follows:

U-Boot
setenv defargs 'core_edp_mv=1300 usb_high_speed=1 mmc_uhs=1'
saveenv
Linux
fw_setenv defargs 'core_edp_mv=1300 usb_high_speed=1 mmc_uhs=1'

Colibri iMX6 V1.1x, Colibri iMX7D/S

This feature of the Linux SDHCI driver may be activated for Colibri iMX6/7 by adding a SD_1_8 define to the appropriate DTS file of your board. For example for the Colibri iMX6DL add the define to imx6qdl-colibri.dtsi:

diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
index 23770786ab77..135c00edd5c4 100644
--- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
@@ -1039,6 +1039,8 @@
  * 3.3V to 1.8V under the usdhc1's drivers control which is supported starting
  * with hardware revision V1.1A.
  */
+#define SD_1_8
+
 #ifdef SD_1_8
        pinctrl-names = "default", "state_100mhz", "state_200mhz";
        pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_mmc_cd>;

It may also already be enabled on some SoMs by default, for additional details check table below:

SoMs with UHS-I support:

System On Module Embedded Linux BSP version
Apalis T30 (optional on first SD slot only) V2.3 beta 5 and later
Apalis TK1 2.7 and later
Apalis iMX8 3.0 beta 1 and later
Colibri iMX6DL/iMX6ULL (optional) 2.7 and 2.8b5 and later
Colibri iMX7D/S (optional) 2.7 and later
Colibri iMX8X 3.0 beta 1 and later

Using Card with UHS-I Enabled

[   42.946377] mmc1: host does not support reading read-only switch. assuming write-enable.
[   42.957696] mmc1: new ultra high speed DDR SDHC card at address 1234
[   42.966791] mmcblk1: mmc1:1234 SA08G 7.42 GiB 
[   42.973415]  mmcblk1: p1

root@apalis-t30:~# cat /sys/kernel/debug/mmc1/ios 
clock:          50000000 Hz
vdd:            17 (2.9 ~ 3.0 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      2 (4 bits)
timing spec:    5 (invalid)

oot@apalis-t30:~# hdparm -t /dev/mmcblk1

/dev/mmcblk1:
 Timing buffered disk reads:  98 MB in  3.04 seconds =  32.25 MB/sec
root@apalis-t30:~# hdparm -t /dev/mmcblk1

/dev/mmcblk1:
 Timing buffered disk reads:  98 MB in  3.03 seconds =  32.38 MB/sec
root@apalis-t30:~# hdparm -t /dev/mmcblk1

/dev/mmcblk1:
 Timing buffered disk reads:  98 MB in  3.02 seconds =  32.41 MB/sec

Using Card Without UHS-I Enabled

[   68.134332] mmc1: host does not support reading read-only switch. assuming write-enable.
[   68.144952] mmc1: new high speed SDHC card at address 1234
[   68.152959] mmcblk1: mmc1:1234 SA08G 7.42 GiB 
[   68.161914]  mmcblk1: p1

root@apalis-t30:~# cat /sys/kernel/debug/mmc1/ios 
clock:          50000000 Hz
vdd:            17 (2.9 ~ 3.0 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      2 (4 bits)
timing spec:    2 (sd high-speed)

root@apalis-t30:~# hdparm -t /dev/mmcblk1

/dev/mmcblk1:
 Timing buffered disk reads:  56 MB in  3.03 seconds =  18.46 MB/sec
root@apalis-t30:~# hdparm -t /dev/mmcblk1

/dev/mmcblk1:
 Timing buffered disk reads:  56 MB in  3.03 seconds =  18.45 MB/sec
root@apalis-t30:~# hdparm -t /dev/mmcblk1

/dev/mmcblk1:
 Timing buffered disk reads:  56 MB in  3.04 seconds =  18.44 MB/sec