The Flexible Memory Controller (FMC) host driver implements a standard Linux driver interface to support NAND devices. The host driver is part of the Linux kernel MTD framework.

The STM32MP15 CPU has one FMC controller.

On the ConnectCore MP15 system-on-module:

  • FMC connects internally to the NAND chip using eight data lines and NAND control lines.

Kernel configuration

You can manage the FMC driver support through the following kernel configuration option:

  • Support for NAND controller on STM32MP SoCs (CONFIG_MTD_NAND_STM32_FMC2)

This option is enabled as built-in on the default ConnectCore MP15 kernel configuration file.

Kernel driver

The driver for the FMC is located at:

File Description

drivers/mtd/nand/raw/stm32_fmc2_nand.c

FMC driver

Device tree bindings and customization

The FMC device tree binding is documented at Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml.

Common NAND device tree bindings are documented at Documentation/devicetree/bindings/mtd/nand-controller.yaml.

The common STM32MP15 CPU device tree defines all the FMC ports, including the NAND controller.

STM32MP15 device tree
fmc: memory-controller@58002000 {
	#address-cells = <2>;
	#size-cells = <1>;
	compatible = "st,stm32mp1-fmc2-ebi";
	reg = <0x58002000 0x1000>;
	clocks = <&rcc FMC_K>;
	resets = <&rcc FMC_R>;
	status = "disabled";

	ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
		 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
		 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
		 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
		 <4 0 0x80000000 0x10000000>; /* NAND */

	nand-controller@4,0 {
		#address-cells = <1>;
		#size-cells = <0>;
		compatible = "st,stm32mp1-fmc2-nfc";
		reg = <4 0x00000000 0x1000>,
		      <4 0x08010000 0x1000>,
		      <4 0x08020000 0x1000>,
		      <4 0x01000000 0x1000>,
		      <4 0x09010000 0x1000>,
		      <4 0x09020000 0x1000>;
		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
		dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0 0x0>,
		       <&mdma1 20 0x2 0x12000a08 0x0 0x0 0x0>,
		       <&mdma1 21 0x2 0x12000a0a 0x0 0x0 0x0>;
		dma-names = "tx", "rx", "ecc";
		status = "disabled";
	};

	[...]

};

The ConnectCore MP15 device tree enables the nand controller of the FMC interface using eight data lines.

ConnectCore MP15 device tree
&fmc {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&fmc_pins_a>;
	pinctrl-1 = <&fmc_sleep_pins_a>;
	status = "okay";

	nand-controller@4,0 {
		status = "okay";

		nand@0 {
			reg = <0>;
			nand-on-flash-bbt;
			#address-cells = <1>;
			#size-cells = <1>;
		};
	};
};

IOMUX configuration

ConnectCore MP15 device tree
&pinctrl {
	fmc_pins_a: fmc-0 {
		pins1 {
			pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
				 <STM32_PINMUX('D', 5, AF12)>, /* FMC_NWE */
				 <STM32_PINMUX('D', 11, AF12)>, /* FMC_A16_FMC_CLE */
				 <STM32_PINMUX('D', 12, AF12)>, /* FMC_A17_FMC_ALE */
				 <STM32_PINMUX('D', 14, AF12)>, /* FMC_D0 */
				 <STM32_PINMUX('D', 15, AF12)>, /* FMC_D1 */
				 <STM32_PINMUX('D', 0, AF12)>, /* FMC_D2 */
				 <STM32_PINMUX('D', 1, AF12)>, /* FMC_D3 */
				 <STM32_PINMUX('E', 7, AF12)>, /* FMC_D4 */
				 <STM32_PINMUX('E', 8, AF12)>, /* FMC_D5 */
				 <STM32_PINMUX('E', 9, AF12)>, /* FMC_D6 */
				 <STM32_PINMUX('E', 10, AF12)>, /* FMC_D7 */
				 <STM32_PINMUX('G', 9, AF12)>; /* FMC_NE2_FMC_NCE */
			bias-disable;
			drive-push-pull;
			slew-rate = <1>;
		};
		pins2 {
			pinmux = <STM32_PINMUX('D', 6, AF12)>; /* FMC_NWAIT */
			bias-pull-up;
		};
	};

	fmc_sleep_pins_a: fmc-sleep-0 {
		pins {
			pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
				 <STM32_PINMUX('D', 5, ANALOG)>, /* FMC_NWE */
				 <STM32_PINMUX('D', 11, ANALOG)>, /* FMC_A16_FMC_CLE */
				 <STM32_PINMUX('D', 12, ANALOG)>, /* FMC_A17_FMC_ALE */
				 <STM32_PINMUX('D', 14, ANALOG)>, /* FMC_D0 */
				 <STM32_PINMUX('D', 15, ANALOG)>, /* FMC_D1 */
				 <STM32_PINMUX('D', 0, ANALOG)>, /* FMC_D2 */
				 <STM32_PINMUX('D', 1, ANALOG)>, /* FMC_D3 */
				 <STM32_PINMUX('E', 7, ANALOG)>, /* FMC_D4 */
				 <STM32_PINMUX('E', 8, ANALOG)>, /* FMC_D5 */
				 <STM32_PINMUX('E', 9, ANALOG)>, /* FMC_D6 */
				 <STM32_PINMUX('E', 10, ANALOG)>, /* FMC_D7 */
				 <STM32_PINMUX('D', 6, ANALOG)>, /* FMC_NWAIT */
				 <STM32_PINMUX('G', 9, ANALOG)>; /* FMC_NE2_FMC_NCE */
		};
	};
};

User space usage

On a NAND flash memory, the partitions are established by a kernel parameter (a string) which is passed by the bootloader. See Storage layout for information about the partition layout.

On Linux, you can check the partition table with this command:

# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00020000 "fsbl1"
mtd1: 00080000 00020000 "fsbl2"
mtd2: 00080000 00020000 "metadata1"
mtd3: 00080000 00020000 "metadata2"
mtd4: 00300000 00020000 "fip-a"
mtd5: 00300000 00020000 "fip-b"
mtd6: 0f800000 00020000 "UBI"

Partition "UBI" contains several UBI volumes. UBI volumes with a file system can be mounted with mount command.