The MultiMediaCard (MMC)/Secure Digital (SD)/Secure Digital Input Output (SDIO) host driver implements a standard Linux driver interface to the ultra MMC/SD host controller (uSDHC). The host driver is part of the Linux kernel MMC framework.

Features

The i.MX8QXP MMC driver supports:

  • MMC and SD cards

  • SDIO cards

  • SD3.0 cards

MMC on the ConnectCore 8X platforms

On the ConnectCore 8X system-on-module:

  • Internal eMMC is connected to uSDHC0 controller using eight data lines.

On the ConnectCore 8X SBC Pro:

  • microSD card holder is connected to uSDHC1 controller using four data lines and a card detection line. It is available on the bottom side of the board.

Kernel configuration

You can manage the MMC/uSDHC driver support through the following kernel configuration options:

  • MMC/SD/SDIO (CONFIG_MMC)

  • MMC block (CONFIG_MMC_BLOCK)

  • Secure Digital Host Controller Interface support (CONFIG_MMC_SDHCI)

  • SDHCI support on the platform-specific bus (CONFIG_MMC_SDHCI_PLTFM)

  • SDHCI platform support for the NXP eSDHC i.MX controller (CONFIG_MMC_SDHCI_ESDHC_IMX)

These options are enabled as built-in on the default ConnectCore 8X kernel configuration file.

Kernel driver

The table below shows the uSDHC source files available in the kernel source directory: drivers/mmc/host/.

File Description

sdhci.c

standard stack code

sdhci-pltfm.c

sdhci platform layer

sdhci-esdhc-imx.c

uSDHC driver

sdhci-esdhc.h

uSDHC driver header file

Device tree bindings and customization

The i.MX8QXP MMC/SD/SDIO interface device tree binding is documented at Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt.

Common MMC device tree bindings are documented at Documentation/devicetree/bindings/mmc/mmc.txt.

The MMC/SD/SDIO interfaces are defined in the i.MX8QXP CPU, ConnectCore 8X system-on-module, and ConnectCore 8X SBC Pro device tree files.

The common i.MX8QXP CPU device tree defines all the uSDHC ports. The platform device tree must:

  • Enable the required uSDHC port, by setting the status property to okay.

  • Select the bus-width depending on the number of data lines to use.

  • Select optional properties (broken-cd, no-1-8-v, non-removable…​), depending on the interface (see binding documentation).

  • Configure the IOMUX of the pads to use for the interface.

Example: eMMC

On the ConnectCore 8X, the eMMC is connected to uSDHC0 controller using eight data lines.

Definition of the uSDHC0

On the device tree, uSDHC0 is represented by node usdhc1.
i.MX8QXP device tree
usdhc1: usdhc@5b010000 {
	compatible = "fsl,imx8qm-usdhc", "fsl,imx6sl-usdhc";
	interrupt-parent = <&gic>;
	interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
	reg = <0x0 0x5b010000 0x0 0x10000>;
	clocks = <&clk IMX8QXP_SDHC0_IPG_CLK>,
		 <&clk IMX8QXP_SDHC0_CLK>,
		 <&clk IMX8QXP_CLK_DUMMY>;
	clock-names = "ipg", "per", "ahb";
	assigned-clocks = <&clk IMX8QXP_SDHC0_SEL>, <&clk IMX8QXP_SDHC0_DIV>;
	assigned-clock-parents = <&clk IMX8QXP_CONN_PLL1_CLK>;
	assigned-clock-rates = <0>, <400000000>;
	power-domains = <&pd_conn_sdch0>;
	fsl,tuning-start-tap = <20>;
	fsl,tuning-step= <2>;
	status = "okay";
};

IOMUX configuration

ConnectCore 8X device tree
/* eMMC */
pinctrl_usdhc1: usdhc1grp {
	fsl,pins = <
		SC_P_EMMC0_CLK_CONN_EMMC0_CLK		0x06000041
		SC_P_EMMC0_CMD_CONN_EMMC0_CMD		0x00000021
		SC_P_EMMC0_DATA0_CONN_EMMC0_DATA0	0x00000021
		SC_P_EMMC0_DATA1_CONN_EMMC0_DATA1	0x00000021
		SC_P_EMMC0_DATA2_CONN_EMMC0_DATA2	0x00000021
		SC_P_EMMC0_DATA3_CONN_EMMC0_DATA3	0x00000021
		SC_P_EMMC0_DATA4_CONN_EMMC0_DATA4	0x00000021
		SC_P_EMMC0_DATA5_CONN_EMMC0_DATA5	0x00000021
		SC_P_EMMC0_DATA6_CONN_EMMC0_DATA6	0x00000021
		SC_P_EMMC0_DATA7_CONN_EMMC0_DATA7	0x00000021
		SC_P_EMMC0_STROBE_CONN_EMMC0_STROBE	0x06000041
	>;
};

Device enabling and options

ConnectCore 8X device tree
/* eMMC */
&usdhc1 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc1>;
	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
	bus-width = <8>;
	non-removable;
	/*
	 * This property should be removed once the eMMC voltage is configured
	 * to 1.8V.
	 */
	no-1-8-v;
	status = "okay";
};

Example: microSD on the ConnectCore 8X SBC Pro

On the ConnectCore 8X SBC Pro, the microSD card holder is connected to uSDHC1 controller using four data lines and a card detection line.

Definition of the uSDHC1

On the device tree, uSDHC1 is represented by node usdhc2.
i.MX8QXP device tree
usdhc2: usdhc@5b020000 {
	compatible = "fsl,imx8qm-usdhc", "fsl,imx6sl-usdhc";
	interrupt-parent = <&gic>;
	interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
	reg = <0x0 0x5b020000 0x0 0x10000>;
	clocks = <&clk IMX8QXP_SDHC1_IPG_CLK>,
		 <&clk IMX8QXP_SDHC1_CLK>,
		 <&clk IMX8QXP_CLK_DUMMY>;
	clock-names = "ipg", "per", "ahb";
	assigned-clocks = <&clk IMX8QXP_SDHC1_SEL>, <&clk IMX8QXP_SDHC1_DIV>;
	assigned-clock-parents = <&clk IMX8QXP_CONN_PLL1_CLK>;
	assigned-clock-rates = <0>, <200000000>;
	power-domains = <&pd_conn_sdch1>;
	fsl,tuning-start-tap = <20>;
	fsl,tuning-step= <2>;
	status = "okay";
};

IOMUX configuration

ConnectCore 8X SBC Pro device tree
	pinctrl_usdhc2_gpio: usdhc2gpiogrp {
		fsl,pins = <
			/* Card detect */
			SC_P_USDHC1_CD_B_LSIO_GPIO4_IO22	0x06000021
		>;
	};

	pinctrl_usdhc2: usdhc2grp {
		fsl,pins = <
			SC_P_USDHC1_CLK_CONN_USDHC1_CLK		0x06000041
			SC_P_USDHC1_CMD_CONN_USDHC1_CMD		0x00000021
			SC_P_USDHC1_DATA0_CONN_USDHC1_DATA0	0x00000021
			SC_P_USDHC1_DATA1_CONN_USDHC1_DATA1	0x00000021
			SC_P_USDHC1_DATA2_CONN_USDHC1_DATA2	0x00000021
			SC_P_USDHC1_DATA3_CONN_USDHC1_DATA3	0x00000021
		>;
	};

	pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
		fsl,pins = <
			SC_P_USDHC1_CLK_CONN_USDHC1_CLK		0x06000041
			SC_P_USDHC1_CMD_CONN_USDHC1_CMD		0x00000021
			SC_P_USDHC1_DATA0_CONN_USDHC1_DATA0	0x00000021
			SC_P_USDHC1_DATA1_CONN_USDHC1_DATA1	0x00000021
			SC_P_USDHC1_DATA2_CONN_USDHC1_DATA2	0x00000021
			SC_P_USDHC1_DATA3_CONN_USDHC1_DATA3	0x00000021
		>;
	};

	pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
		fsl,pins = <
			SC_P_USDHC1_CLK_CONN_USDHC1_CLK		0x06000041
			SC_P_USDHC1_CMD_CONN_USDHC1_CMD		0x00000021
			SC_P_USDHC1_DATA0_CONN_USDHC1_DATA0	0x00000021
			SC_P_USDHC1_DATA1_CONN_USDHC1_DATA1	0x00000021
			SC_P_USDHC1_DATA2_CONN_USDHC1_DATA2	0x00000021
			SC_P_USDHC1_DATA3_CONN_USDHC1_DATA3	0x00000021
		>;
	};

Device enabling and options

ConnectCore 8X SBC Pro device tree
/* Micro SD card */
&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
	bus-width = <4>;
	no-1-8-v;
	cd-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
	status = "okay";
};

User space usage

The MMC block driver handles the file system read/write calls and uses the low-level MMC host controller interface driver to send the commands to the uSDHC controller.

The MMC device driver exposes the device through the file system at /dev/mmcblkX where X is a number, starting at zero, that indicates the device index.

If the block device is partitioned, the partitions will appear as /dev/mmcblkXpY where Y is a number, starting at one, that indicates the partition index.

By default, formatted partitions are auto-mounted upon detection if they are block devices.

You can also mount a partition’s file system using the mount command with the partition node, the file system type, and the mount point:

~# mkdir -p /run/media/mmcblk1p1 && mount -t vfat /dev/mmcblk1p1 /run/media/mmcblk1p1

MMC/SD/SDIO on the ConnectCore 8X boards

Device node mapping

On the ConnectCore 8X SBC Pro device tree, the uSDHC interfaces are set up to be mapped by Linux as follows:

  • The eMMC (connected to uSDHC0) is mapped to /dev/mmcblk0.

  • The microSD card (connected to uSDHC1) is mapped to /dev/mmcblk1.

microSD card detection

The microSD card holder on the ConnectCore 8X SBC Pro has card detection line.

Formatted partitions are auto-mounted upon card insertion.

If the device (microSD or eMMC) is not partitioned, you can use fdisk to create one partition of type vfat and then give it format with mkfs, for example:

~# echo -e 'o\nn\np\n1\n\n\nt\nb\nw\n' | fdisk /dev/mmcblk1 > /dev/null
~# mkfs.vfat /dev/mmcblk1p1

If the device is partitioned but you still want to re-partition or re-format it, you must first unmount all the mounted partitions.