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.MX93 MMC driver supports:

  • MMC and SD cards

  • SDIO cards

  • SD3.0 cards

MMC on the ConnectCore 93 platforms

On the ConnectCore 93 system-on-module:

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

On the ConnectCore 93 Development Kit:

  • J23 microSD card holder is connected to uSDHC2 controller using four data lines and a card detection line.

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 93 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.MX93 MMC/SD/SDIO interface device tree binding is documented at Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml.

Common MMC device tree bindings are documented at Documentation/devicetree/bindings/mmc/mmc-controller.yaml.

The MMC/SD/SDIO interfaces are defined in the i.MX93 CPU, ConnectCore 93 system-on-module, and ConnectCore 93 Development Kit device tree files.

The common i.MX93 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.

Do not modify the uSDHC3 controller because it is used to communicate with the Wi-Fi chip and defined in the ccimx93.dtsi include file:

ConnectCore 93 device tree
/* Wifi MAC */
&usdhc3 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_wlan>;
	pinctrl-1 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_wlan>;
	pinctrl-2 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_wlan>;

	mmc-pwrseq = <&wlan_pwrseq>;
	bus-width = <4>;
	non-removable;
	wakeup-source;
	fsl,sdio-async-interrupt-enabled;
	status = "disabled";
};

Example: eMMC

On the ConnectCore 93, the eMMC is connected to uSDHC3 controller using eight data lines.

Definition of the uSDHC3

i.MX93 device tree
usdhc1: mmc@42850000 {
	compatible = "fsl,imx93-usdhc", "fsl,imx8mm-usdhc";
	reg = <0x42850000 0x10000>;
	interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clk IMX93_CLK_BUS_WAKEUP>,
			<&clk IMX93_CLK_WAKEUP_AXI>,
			<&clk IMX93_CLK_USDHC1_GATE>;
	clock-names = "ipg", "ahb", "per";
	assigned-clocks = <&clk IMX93_CLK_USDHC1>;
	assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1>;
	assigned-clock-rates = <400000000>;
	bus-width = <8>;
	fsl,tuning-start-tap = <40>;
	fsl,tuning-step= <1>;
	status = "disabled";
};

IOMUX configuration

ConnectCore 93 device tree
	/* eMMC */
	pinctrl_usdhc1: usdhc1grp {
		fsl,pins = <
			MX93_PAD_SD1_CLK__USDHC1_CLK			0x17fe
			MX93_PAD_SD1_CMD__USDHC1_CMD			0x13fe
			MX93_PAD_SD1_DATA0__USDHC1_DATA0		0x13fe
			MX93_PAD_SD1_DATA1__USDHC1_DATA1		0x13fe
			MX93_PAD_SD1_DATA2__USDHC1_DATA2		0x13fe
			MX93_PAD_SD1_DATA3__USDHC1_DATA3		0x13fe
			MX93_PAD_SD1_DATA4__USDHC1_DATA4		0x13fe
			MX93_PAD_SD1_DATA5__USDHC1_DATA5		0x13fe
			MX93_PAD_SD1_DATA6__USDHC1_DATA6		0x13fe
			MX93_PAD_SD1_DATA7__USDHC1_DATA7		0x13fe
			MX93_PAD_SD1_STROBE__USDHC1_STROBE		0x17fe
		>;
	};

Device enabling and options

ConnectCore 93 device tree
/* eMMC */
&usdhc1 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc1>;
	pinctrl-1 = <&pinctrl_usdhc1>;
	pinctrl-2 = <&pinctrl_usdhc1>;
	bus-width = <8>;
	non-removable;
	status = "okay";
};

Example: microSD on the ConnectCore 93 Development Kit

On the ConnectCore 93 Development Kit, the microSD card holder is connected to uSDHC2 controller using four data lines and a card detection line. Runtime voltage select is not currently supported, and microSD card/bus voltage is set to 3.3 V by default.

Definition of the uSDHC2

i.MX93 device tree
usdhc2: mmc@42860000 {
	compatible = "fsl,imx93-usdhc", "fsl,imx8mm-usdhc";
	reg = <0x42860000 0x10000>;
	interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clk IMX93_CLK_BUS_WAKEUP>,
			<&clk IMX93_CLK_WAKEUP_AXI>,
			<&clk IMX93_CLK_USDHC2_GATE>;
	clock-names = "ipg", "ahb", "per";
	assigned-clocks = <&clk IMX93_CLK_USDHC2>;
	assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1>;
	assigned-clock-rates = <400000000>;
	bus-width = <4>;
	fsl,tuning-start-tap = <20>;
	fsl,tuning-step= <2>;
	status = "disabled";
};

IOMUX configuration

ConnectCore 93 Development Kit device tree
	/* SD card */
	pinctrl_usdhc2_gpio: usdhc2gpiogrp {
		fsl,pins = <
			MX93_PAD_SD2_CD_B__GPIO3_IO00				0x31e
		>;
	};

	pinctrl_usdhc2: usdhc2grp {
		fsl,pins = <
			MX93_PAD_SD2_CLK__USDHC2_CLK				0x17fe
			MX93_PAD_SD2_CMD__USDHC2_CMD				0x13fe
			MX93_PAD_SD2_DATA0__USDHC2_DATA0			0x13fe
			MX93_PAD_SD2_DATA1__USDHC2_DATA1			0x13fe
			MX93_PAD_SD2_DATA2__USDHC2_DATA2			0x13fe
			MX93_PAD_SD2_DATA3__USDHC2_DATA3			0x13fe
			MX93_PAD_SD2_VSELECT__USDHC2_VSELECT			0x51e
		>;
	};

Device enabling and options

ConnectCore 93 Development Kit device tree
/* SD card */
&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
	pinctrl-1 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
	pinctrl-2 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
	cd-gpios = <&gpio3 00 GPIO_ACTIVE_HIGH>;
	bus-width = <4>;
	status = "okay";
	post-power-on-delay-ms = <200>;
	no-sdio;
	no-mmc;
};

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 93 boards

Device node mapping

On the ConnectCore 93 Development Kit device tree, the uSDHC interfaces are set up to be mapped by Linux as follows:

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

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

microSD card detection

The microSD card holder on the ConnectCore 93 Development Kit has a 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.