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 uSDHC1 controller using eight data lines.
On the ConnectCore 8X SBC Pro:
-
microSD card holder is connected to uSDHC2 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 |
---|---|
standard stack code |
|
sdhci platform layer |
|
uSDHC driver |
|
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 uSDHC1 controller using eight data lines.
Definition of the uSDHC1
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
/* 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
/* 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 uSDHC2 controller using four data lines and a card detection line.
Definition of the uSDHC2
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
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
/* 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 uSDHC1) 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 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:
If the device is partitioned but you still want to re-partition or re-format it, you must first unmount all the mounted partitions. |