Browse Source

Merge tag 'u-boot-stm32-20200813' of https://gitlab.denx.de/u-boot/custodians/u-boot-stm

  - Use IS_ENABLED to prevent ifdef in board_key_check for STM32MP
  - Add STM32 FMC2 EBI controller driver
  - Fix dwc3-sti-glue which allows STiH410-B2260 to boot again
  - Add fitImage its entry for 587-200 DHCOR SoM
  - Add both PDK2 and DRC02 DT into DHCOM fitImage its
  - Fix DHCOM KS8851 ethernet MAC address
  - Remove stm32mp1 board.c file
  - Use const for struct node_info in board stm32mp1.c file
Tom Rini 3 years ago
parent
commit
6808dc62d7

+ 29 - 14
arch/arm/dts/stm32mp151.dtsi

@@ -1328,23 +1328,38 @@
 			dma-requests = <48>;
 		};
 
-		fmc: nand-controller@58002000 {
-			compatible = "st,stm32mp15-fmc2";
-			reg = <0x58002000 0x1000>,
-			      <0x80000000 0x1000>,
-			      <0x88010000 0x1000>,
-			      <0x88020000 0x1000>,
-			      <0x81000000 0x1000>,
-			      <0x89010000 0x1000>,
-			      <0x89020000 0x1000>;
-			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
-			       <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
-			       <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
-			dma-names = "tx", "rx", "ecc";
+		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>,
+				       <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+				       <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+				dma-names = "tx", "rx", "ecc";
+				status = "disabled";
+			};
 		};
 
 		qspi: spi@58003000 {

+ 9 - 7
arch/arm/dts/stm32mp157c-ev1.dts

@@ -157,14 +157,16 @@
 	pinctrl-0 = <&fmc_pins_a>;
 	pinctrl-1 = <&fmc_sleep_pins_a>;
 	status = "okay";
-	#address-cells = <1>;
-	#size-cells = <0>;
 
-	nand@0 {
-		reg = <0>;
-		nand-on-flash-bbt;
-		#address-cells = <1>;
-		#size-cells = <1>;
+	nand-controller@4,0 {
+		status = "okay";
+
+		nand@0 {
+			reg = <0>;
+			nand-on-flash-bbt;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
 	};
 };
 

+ 1 - 0
arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi

@@ -18,6 +18,7 @@
 		mmc1 = &sdmmc2;
 		spi0 = &qspi;
 		usb0 = &usbotg_hs;
+		ethernet1 = &ksz8851;
 	};
 
 	config {

+ 46 - 40
arch/arm/mach-stm32mp/bsec.c

@@ -74,7 +74,6 @@ static bool bsec_read_lock(u32 address, u32 otp)
 	return !!(readl(address + bank) & bit);
 }
 
-#ifndef CONFIG_TFABOOT
 /**
  * bsec_check_error() - Check status of one otp
  * @base: base address of bsec IP
@@ -279,7 +278,6 @@ static int bsec_program_otp(long base, u32 val, u32 otp)
 
 	return ret;
 }
-#endif /* CONFIG_TFABOOT */
 
 /* BSEC MISC driver *******************************************************/
 struct stm32mp_bsec_platdata {
@@ -288,15 +286,17 @@ struct stm32mp_bsec_platdata {
 
 static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
 {
-#ifdef CONFIG_TFABOOT
-	return stm32_smc(STM32_SMC_BSEC,
-			 STM32_SMC_READ_OTP,
-			 otp, 0, val);
-#else
-	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+	struct stm32mp_bsec_platdata *plat;
 	u32 tmp_data = 0;
 	int ret;
 
+	if (IS_ENABLED(CONFIG_TFABOOT))
+		return stm32_smc(STM32_SMC_BSEC,
+				 STM32_SMC_READ_OTP,
+				 otp, 0, val);
+
+	plat = dev_get_platdata(dev);
+
 	/* read current shadow value */
 	ret = bsec_read_shadow(plat->base, &tmp_data, otp);
 	if (ret)
@@ -313,21 +313,22 @@ static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
 
 	/* restore shadow value */
 	ret = bsec_write_shadow(plat->base, tmp_data, otp);
+
 	return ret;
-#endif
 }
 
 static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
 {
-#ifdef CONFIG_TFABOOT
-	return stm32_smc(STM32_SMC_BSEC,
-			 STM32_SMC_READ_SHADOW,
-			 otp, 0, val);
-#else
-	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+	struct stm32mp_bsec_platdata *plat;
+
+	if (IS_ENABLED(CONFIG_TFABOOT))
+		return stm32_smc(STM32_SMC_BSEC,
+				 STM32_SMC_READ_SHADOW,
+				 otp, 0, val);
+
+	plat = dev_get_platdata(dev);
 
 	return bsec_read_shadow(plat->base, val, otp);
-#endif
 }
 
 static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
@@ -342,33 +343,38 @@ static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
 
 static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
 {
-#ifdef CONFIG_TFABOOT
-	return stm32_smc_exec(STM32_SMC_BSEC,
-			      STM32_SMC_PROG_OTP,
-			      otp, val);
-#else
-	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+	struct stm32mp_bsec_platdata *plat;
+
+	if (IS_ENABLED(CONFIG_TFABOOT))
+		return stm32_smc_exec(STM32_SMC_BSEC,
+				      STM32_SMC_PROG_OTP,
+				      otp, val);
+
+	plat = dev_get_platdata(dev);
 
 	return bsec_program_otp(plat->base, val, otp);
-#endif
+
 }
 
 static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
 {
-#ifdef CONFIG_TFABOOT
-	return stm32_smc_exec(STM32_SMC_BSEC,
-			      STM32_SMC_WRITE_SHADOW,
-			      otp, val);
-#else
-	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+	struct stm32mp_bsec_platdata *plat;
+
+	if (IS_ENABLED(CONFIG_TFABOOT))
+		return stm32_smc_exec(STM32_SMC_BSEC,
+				      STM32_SMC_WRITE_SHADOW,
+				      otp, val);
+
+	plat = dev_get_platdata(dev);
 
 	return bsec_write_shadow(plat->base, val, otp);
-#endif
 }
 
 static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
 {
-#ifdef CONFIG_TFABOOT
+	if (!IS_ENABLED(CONFIG_TFABOOT))
+		return -ENOTSUPP;
+
 	if (val == 1)
 		return stm32_smc_exec(STM32_SMC_BSEC,
 				      STM32_SMC_WRLOCK_OTP,
@@ -377,9 +383,6 @@ static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
 		return 0; /* nothing to do */
 
 	return -EINVAL;
-#else
-	return -ENOTSUPP;
-#endif
 }
 
 static int stm32mp_bsec_read(struct udevice *dev, int offset,
@@ -481,18 +484,21 @@ static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev)
 
 static int stm32mp_bsec_probe(struct udevice *dev)
 {
-#if !defined(CONFIG_TFABOOT) && !defined(CONFIG_SPL_BUILD)
 	int otp;
-	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+	struct stm32mp_bsec_platdata *plat;
 
 	/*
 	 * update unlocked shadow for OTP cleared by the rom code
 	 * only executed in U-Boot proper when TF-A is not used
 	 */
-	for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
-		if (!bsec_read_SR_lock(plat->base, otp))
-			bsec_shadow_register(plat->base, otp);
-#endif
+
+	if (!IS_ENABLED(CONFIG_TFABOOT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
+		plat = dev_get_platdata(dev);
+
+		for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
+			if (!bsec_read_SR_lock(plat->base, otp))
+				bsec_shadow_register(plat->base, otp);
+	}
 
 	return 0;
 }

+ 2 - 3
arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c

@@ -14,7 +14,6 @@ struct stm32prog_data *stm32prog_data;
 
 static void enable_vidconsole(void)
 {
-#ifdef CONFIG_DM_VIDEO
 	char *stdname;
 	char buf[64];
 
@@ -35,7 +34,6 @@ static void enable_vidconsole(void)
 			snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
 		env_set("stderr", buf);
 	}
-#endif
 }
 
 static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -86,7 +84,8 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
 						   "script@1");
 	}
 
-	enable_vidconsole();
+	if (IS_ENABLED(CONFIG_DM_VIDEO))
+		enable_vidconsole();
 
 	data = (struct stm32prog_data *)malloc(sizeof(*data));
 

+ 56 - 44
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c

@@ -544,10 +544,8 @@ static int init_device(struct stm32prog_data *data,
 {
 	struct mmc *mmc = NULL;
 	struct blk_desc *block_dev = NULL;
-#ifdef CONFIG_MTD
 	struct mtd_info *mtd = NULL;
 	char mtd_id[16];
-#endif
 	int part_id;
 	int ret;
 	u64 first_addr = 0, last_addr = 0;
@@ -557,8 +555,11 @@ static int init_device(struct stm32prog_data *data,
 	const char *part_name;
 
 	switch (dev->target) {
-#ifdef CONFIG_MMC
 	case STM32PROG_MMC:
+		if (!IS_ENABLED(CONFIG_MMC)) {
+			stm32prog_err("unknown device type = %d", dev->target);
+			return -ENODEV;
+		}
 		mmc = find_mmc_device(dev->dev_id);
 		if (!mmc || mmc_init(mmc)) {
 			stm32prog_err("mmc device %d not found", dev->dev_id);
@@ -589,11 +590,13 @@ static int init_device(struct stm32prog_data *data,
 			 first_addr, last_addr);
 		pr_debug(" full_update = %d\n", dev->full_update);
 		break;
-#endif
-#ifdef CONFIG_MTD
 	case STM32PROG_NOR:
 	case STM32PROG_NAND:
 	case STM32PROG_SPI_NAND:
+		if (!IS_ENABLED(CONFIG_MTD)) {
+			stm32prog_err("unknown device type = %d", dev->target);
+			return -ENODEV;
+		}
 		get_mtd_by_target(mtd_id, dev->target, dev->dev_id);
 		pr_debug("%s\n", mtd_id);
 
@@ -612,7 +615,6 @@ static int init_device(struct stm32prog_data *data,
 			 first_addr, last_addr);
 		dev->mtd = mtd;
 		break;
-#endif
 	case STM32PROG_RAM:
 		first_addr = gd->bd->bi_dram[0].start;
 		last_addr = first_addr + gd->bd->bi_dram[0].size;
@@ -744,8 +746,7 @@ static int init_device(struct stm32prog_data *data,
 			part_found = true;
 		}
 
-#ifdef CONFIG_MTD
-		if (mtd) {
+		if (IS_ENABLED(CONFIG_MTD) && mtd) {
 			char mtd_part_id[32];
 			struct part_info *mtd_part;
 			struct mtd_device *mtd_dev;
@@ -766,7 +767,7 @@ static int init_device(struct stm32prog_data *data,
 			part_name = mtd_part->name;
 			part_found = true;
 		}
-#endif
+
 		if (!part_found) {
 			stm32prog_err("%s (0x%x): Invalid partition",
 				      part->name, part->id);
@@ -873,9 +874,8 @@ static int treat_partition_list(struct stm32prog_data *data)
 	return 0;
 }
 
-static int create_partitions(struct stm32prog_data *data)
+static int create_gpt_partitions(struct stm32prog_data *data)
 {
-#ifdef CONFIG_MMC
 	int offset = 0;
 	const int buflen = SZ_8K;
 	char *buf;
@@ -991,7 +991,6 @@ static int create_partitions(struct stm32prog_data *data)
 	run_command("mtd list", 0);
 #endif
 	free(buf);
-#endif
 
 	return 0;
 }
@@ -1070,28 +1069,35 @@ static int stm32prog_alt_add(struct stm32prog_data *data,
 		offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
 				   " %d;", part->part_id);
 	}
+	ret = -ENODEV;
 	switch (part->target) {
-#ifdef CONFIG_MMC
 	case STM32PROG_MMC:
-		sprintf(dfustr, "mmc");
-		sprintf(devstr, "%d", part->dev_id);
+		if (IS_ENABLED(CONFIG_MMC)) {
+			ret = 0;
+			sprintf(dfustr, "mmc");
+			sprintf(devstr, "%d", part->dev_id);
+		}
 		break;
-#endif
-#ifdef CONFIG_MTD
 	case STM32PROG_NAND:
 	case STM32PROG_NOR:
 	case STM32PROG_SPI_NAND:
-		sprintf(dfustr, "mtd");
-		get_mtd_by_target(devstr, part->target, part->dev_id);
+		if (IS_ENABLED(CONFIG_MTD)) {
+			ret = 0;
+			sprintf(dfustr, "mtd");
+			get_mtd_by_target(devstr, part->target, part->dev_id);
+		}
 		break;
-#endif
 	case STM32PROG_RAM:
+		ret = 0;
 		sprintf(dfustr, "ram");
 		sprintf(devstr, "0");
 		break;
 	default:
+		break;
+	}
+	if (ret) {
 		stm32prog_err("invalid target: %d", part->target);
-		return -ENODEV;
+		return ret;
 	}
 	pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf);
 	ret = dfu_alt_add(dfu, dfustr, devstr, buf);
@@ -1213,13 +1219,14 @@ int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
 int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
 		       long *size)
 {
-#ifndef CONFIG_ARM_SMCCC
-	stm32prog_err("OTP update not supported");
-
-	return -1;
-#else
 	int result = 0;
 
+	if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
+		stm32prog_err("OTP update not supported");
+
+		return -1;
+	}
+
 	pr_debug("%s: %x %lx\n", __func__, offset, *size);
 	/* alway read for first packet */
 	if (!offset) {
@@ -1255,19 +1262,19 @@ end_otp_read:
 	pr_debug("%s: result %i\n", __func__, result);
 
 	return result;
-#endif
 }
 
 int stm32prog_otp_start(struct stm32prog_data *data)
 {
-#ifndef CONFIG_ARM_SMCCC
-	stm32prog_err("OTP update not supported");
-
-	return -1;
-#else
 	int result = 0;
 	struct arm_smccc_res res;
 
+	if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
+		stm32prog_err("OTP update not supported");
+
+		return -1;
+	}
+
 	if (!data->otp_part) {
 		stm32prog_err("start OTP without data");
 		return -1;
@@ -1302,7 +1309,6 @@ int stm32prog_otp_start(struct stm32prog_data *data)
 	pr_debug("%s: result %i\n", __func__, result);
 
 	return result;
-#endif
 }
 
 int stm32prog_pmic_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
@@ -1538,19 +1544,20 @@ static int part_delete(struct stm32prog_data *data,
 		       struct stm32prog_part_t *part)
 {
 	int ret = 0;
-#ifdef CONFIG_MMC
 	unsigned long blks, blks_offset, blks_size;
 	struct blk_desc *block_dev = NULL;
- #endif
-#ifdef CONFIG_MTD
 	char cmdbuf[40];
 	char devstr[10];
-#endif
 
 	printf("Erasing %s ", part->name);
 	switch (part->target) {
-#ifdef CONFIG_MMC
 	case STM32PROG_MMC:
+		if (!IS_ENABLED(CONFIG_MMC)) {
+			ret = -1;
+			stm32prog_err("%s (0x%x): erase invalid",
+				      part->name, part->id);
+			break;
+		}
 		printf("on mmc %d: ", part->dev->dev_id);
 		block_dev = mmc_get_blk_desc(part->dev->mmc);
 		blks_offset = lldiv(part->addr, part->dev->mmc->read_bl_len);
@@ -1576,11 +1583,15 @@ static int part_delete(struct stm32prog_data *data,
 				      part->name, part->id);
 		}
 		break;
-#endif
-#ifdef CONFIG_MTD
 	case STM32PROG_NOR:
 	case STM32PROG_NAND:
 	case STM32PROG_SPI_NAND:
+		if (!IS_ENABLED(CONFIG_MTD)) {
+			ret = -1;
+			stm32prog_err("%s (0x%x): erase invalid",
+				      part->name, part->id);
+			break;
+		}
 		get_mtd_by_target(devstr, part->target, part->dev->dev_id);
 		printf("on %s: ", devstr);
 		sprintf(cmdbuf, "mtd erase %s 0x%llx 0x%llx",
@@ -1591,7 +1602,6 @@ static int part_delete(struct stm32prog_data *data,
 				      part->name, part->id, cmdbuf);
 		}
 		break;
-#endif
 	case STM32PROG_RAM:
 		printf("on ram: ");
 		memset((void *)(uintptr_t)part->addr, 0, (size_t)part->size);
@@ -1639,9 +1649,11 @@ static void stm32prog_devices_init(struct stm32prog_data *data)
 			goto error;
 	}
 
-	ret = create_partitions(data);
-	if (ret)
-		goto error;
+	if (IS_ENABLED(CONFIG_MMC)) {
+		ret = create_gpt_partitions(data);
+		if (ret)
+			goto error;
+	}
 
 	/* delete partition GPT or MTD */
 	for (i = 0; i < data->part_nb; i++) {

+ 29 - 4
board/dhelectronics/dh_stm32mp1/board.c

@@ -84,11 +84,26 @@ DECLARE_GLOBAL_DATA_PTR;
 int setup_mac_address(void)
 {
 	unsigned char enetaddr[6];
+	bool skip_eth0 = false;
+	bool skip_eth1 = false;
 	struct udevice *dev;
 	int off, ret;
 
 	ret = eth_env_get_enetaddr("ethaddr", enetaddr);
 	if (ret)	/* ethaddr is already set */
+		skip_eth0 = true;
+
+	off = fdt_path_offset(gd->fdt_blob, "ethernet1");
+	if (off < 0) {
+		/* ethernet1 is not present in the system */
+		skip_eth1 = true;
+	} else {
+		ret = eth_env_get_enetaddr("eth1addr", enetaddr);
+		if (ret)	/* eth1addr is already set */
+			skip_eth1 = true;
+	}
+
+	if (skip_eth0 && skip_eth1)
 		return 0;
 
 	off = fdt_path_offset(gd->fdt_blob, "eeprom0");
@@ -109,8 +124,14 @@ int setup_mac_address(void)
 		return ret;
 	}
 
-	if (is_valid_ethaddr(enetaddr))
-		eth_env_set_enetaddr("ethaddr", enetaddr);
+	if (is_valid_ethaddr(enetaddr)) {
+		if (!skip_eth0)
+			eth_env_set_enetaddr("ethaddr", enetaddr);
+
+		enetaddr[5]++;
+		if (!skip_eth1)
+			eth_env_set_enetaddr("eth1addr", enetaddr);
+	}
 
 	return 0;
 }
@@ -216,9 +237,13 @@ int board_early_init_f(void)
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
-	char test[20];
+	const char *compat;
+	char test[128];
+
+	compat = fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
 
-	snprintf(test, sizeof(test), "somrev%d_boardrev%d", somcode, brdcode);
+	snprintf(test, sizeof(test), "%s_somrev%d_boardrev%d",
+		compat, somcode, brdcode);
 
 	if (!strcmp(name, test))
 		return 0;

+ 31 - 1
board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its

@@ -23,17 +23,47 @@
 			arch = "arm";
 			compression = "none";
 		};
+
+		fdt-2 {
+			description = ".dtb";
+			data = /incbin/("arch/arm/dts/stm32mp15xx-dhcom-drc02.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+		};
 	};
 
 	configurations {
 		default = "config-1";
 
 		config-1 {
-			description = "somrev0_boardrev0"; /* SoM+board model */
+			/* DT+SoM+board model */
+			description = "dh,stm32mp15xx-dhcom-pdk2_somrev0_boardrev0";
+			loadables = "uboot";
+			fdt = "fdt-1";
+		};
+
+		config-2 {
+			/* DT+SoM+board model */
+			description = "dh,stm32mp15xx-dhcom-pdk2_somrev1_boardrev0";
 			loadables = "uboot";
 			fdt = "fdt-1";
 		};
 
+		config-3 {
+			/* DT+SoM+board model */
+			description = "dh,stm32mp15xx-dhcom-drc02_somrev0_boardrev0";
+			loadables = "uboot";
+			fdt = "fdt-2";
+		};
+
+		config-4 {
+			/* DT+SoM+board model */
+			description = "dh,stm32mp15xx-dhcom-drc02_somrev1_boardrev0";
+			loadables = "uboot";
+			fdt = "fdt-2";
+		};
+
 		/* Add 587-100..587-400 with fdt-2..fdt-4 here */
 	};
 };

+ 2 - 1
board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its

@@ -29,7 +29,8 @@
 		default = "config-1";
 
 		config-1 {
-			description = "somrev0_boardrev1"; /* SoM+board model */
+			/* DT+SoM+board model */
+			description = "arrow,stm32mp15xx-avenger96_somrev0_boardrev1";
 			loadables = "uboot";
 			fdt = "fdt-1";
 		};

+ 11 - 9
board/st/common/stm32mp_dfu.c

@@ -114,11 +114,13 @@ void set_dfu_alt_info(char *interface, char *devstr)
 	snprintf(buf, DFU_ALT_BUF_LEN,
 		 "ram 0=%s", CONFIG_DFU_ALT_RAM0);
 
-	if (!uclass_get_device(UCLASS_MMC, 0, &dev))
-		board_get_alt_info_mmc(dev, buf);
+	if (CONFIG_IS_ENABLED(MMC)) {
+		if (!uclass_get_device(UCLASS_MMC, 0, &dev))
+			board_get_alt_info_mmc(dev, buf);
 
-	if (!uclass_get_device(UCLASS_MMC, 1, &dev))
-		board_get_alt_info_mmc(dev, buf);
+		if (!uclass_get_device(UCLASS_MMC, 1, &dev))
+			board_get_alt_info_mmc(dev, buf);
+	}
 
 	if (CONFIG_IS_ENABLED(MTD)) {
 		/* probe all MTD devices */
@@ -140,12 +142,12 @@ void set_dfu_alt_info(char *interface, char *devstr)
 			board_get_alt_info_mtd(mtd, buf);
 	}
 
-#ifdef CONFIG_DFU_VIRT
-	strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
+	if (IS_ENABLED(CONFIG_DFU_VIRT)) {
+		strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
 
-	if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
-		strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
-#endif
+		if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
+			strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
+	}
 
 	env_set("dfu_alt_info", buf);
 	puts("DFU alt info setting: done\n");

+ 0 - 36
board/st/stm32mp1/board.c

@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-
-#ifdef CONFIG_DEBUG_UART_BOARD_INIT
-void board_debug_uart_init(void)
-{
-#if (CONFIG_DEBUG_UART_BASE == STM32_UART4_BASE)
-
-#define RCC_MP_APB1ENSETR (STM32_RCC_BASE + 0x0A00)
-#define RCC_MP_AHB4ENSETR (STM32_RCC_BASE + 0x0A28)
-
-	/* UART4 clock enable */
-	setbits_le32(RCC_MP_APB1ENSETR, BIT(16));
-
-#define GPIOG_BASE 0x50008000
-	/* GPIOG clock enable */
-	writel(BIT(6), RCC_MP_AHB4ENSETR);
-	/* GPIO configuration for EVAL board
-	 * => Uart4 TX = G11
-	 */
-	writel(0xffbfffff, GPIOG_BASE + 0x00);
-	writel(0x00006000, GPIOG_BASE + 0x24);
-#else
-
-#error("CONFIG_DEBUG_UART_BASE: not supported value")
-
-#endif
-}
-#endif

+ 99 - 102
board/st/stm32mp1/stm32mp1.c

@@ -135,60 +135,61 @@ int checkboard(void)
 
 static void board_key_check(void)
 {
-#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
 	ofnode node;
 	struct gpio_desc gpio;
 	enum forced_boot_mode boot_mode = BOOT_NORMAL;
 
+	if (!IS_ENABLED(CONFIG_FASTBOOT) && !IS_ENABLED(CONFIG_CMD_STM32PROG))
+		return;
+
 	node = ofnode_path("/config");
 	if (!ofnode_valid(node)) {
 		debug("%s: no /config node?\n", __func__);
 		return;
 	}
-#ifdef CONFIG_FASTBOOT
-	if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
-				       &gpio, GPIOD_IS_IN)) {
-		debug("%s: could not find a /config/st,fastboot-gpios\n",
-		      __func__);
-	} else {
-		if (dm_gpio_get_value(&gpio)) {
-			puts("Fastboot key pressed, ");
-			boot_mode = BOOT_FASTBOOT;
-		}
+	if (IS_ENABLED(CONFIG_FASTBOOT)) {
+		if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
+					       &gpio, GPIOD_IS_IN)) {
+			debug("%s: could not find a /config/st,fastboot-gpios\n",
+			      __func__);
+		} else {
+			if (dm_gpio_get_value(&gpio)) {
+				puts("Fastboot key pressed, ");
+				boot_mode = BOOT_FASTBOOT;
+			}
 
-		dm_gpio_free(NULL, &gpio);
+			dm_gpio_free(NULL, &gpio);
+		}
 	}
-#endif
-#ifdef CONFIG_CMD_STM32PROG
-	if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
-				       &gpio, GPIOD_IS_IN)) {
-		debug("%s: could not find a /config/st,stm32prog-gpios\n",
-		      __func__);
-	} else {
-		if (dm_gpio_get_value(&gpio)) {
-			puts("STM32Programmer key pressed, ");
-			boot_mode = BOOT_STM32PROG;
+	if (IS_ENABLED(CONFIG_CMD_STM32PROG)) {
+		if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
+					       &gpio, GPIOD_IS_IN)) {
+			debug("%s: could not find a /config/st,stm32prog-gpios\n",
+			      __func__);
+		} else {
+			if (dm_gpio_get_value(&gpio)) {
+				puts("STM32Programmer key pressed, ");
+				boot_mode = BOOT_STM32PROG;
+			}
+			dm_gpio_free(NULL, &gpio);
 		}
-		dm_gpio_free(NULL, &gpio);
 	}
-#endif
-
 	if (boot_mode != BOOT_NORMAL) {
 		puts("entering download mode...\n");
 		clrsetbits_le32(TAMP_BOOT_CONTEXT,
 				TAMP_BOOT_FORCED_MASK,
 				boot_mode);
 	}
-#endif
 }
 
-#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
-#include <usb/dwc2_udc.h>
 int g_dnl_board_usb_cable_connected(void)
 {
 	struct udevice *dwc2_udc_otg;
 	int ret;
 
+	if (!IS_ENABLED(CONFIG_USB_GADGET_DWC2_OTG))
+		return -ENODEV;
+
 	/* if typec stusb160x is present, means DK1 or DK2 board */
 	ret = stusb160x_cable_connected();
 	if (ret >= 0)
@@ -203,14 +204,17 @@ int g_dnl_board_usb_cable_connected(void)
 	return dwc2_udc_B_session_valid(dwc2_udc_otg);
 }
 
+#ifdef CONFIG_USB_GADGET_DOWNLOAD
 #define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11
 #define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb
 
 int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
 {
-	if (!strcmp(name, "usb_dnl_dfu"))
+	if (IS_ENABLED(CONFIG_DFU_OVER_USB) &&
+	    !strcmp(name, "usb_dnl_dfu"))
 		put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct);
-	else if (!strcmp(name, "usb_dnl_fastboot"))
+	else if (IS_ENABLED(CONFIG_FASTBOOT) &&
+		 !strcmp(name, "usb_dnl_fastboot"))
 		put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM,
 			      &dev->idProduct);
 	else
@@ -218,8 +222,7 @@ int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
 
 	return 0;
 }
-
-#endif /* CONFIG_USB_GADGET */
+#endif /* CONFIG_USB_GADGET_DOWNLOAD */
 
 static int get_led(struct udevice **dev, char *led_string)
 {
@@ -285,7 +288,6 @@ static void __maybe_unused led_error_blink(u32 nb_blink)
 		hang();
 }
 
-#ifdef CONFIG_ADC
 static int board_check_usb_power(void)
 {
 	struct ofnode_phandle_args adc_args;
@@ -297,6 +299,10 @@ static int board_check_usb_power(void)
 	int ret, uV, adc_count;
 	u32 nb_blink;
 	u8 i;
+
+	if (!IS_ENABLED(CONFIG_ADC))
+		return -ENODEV;
+
 	node = ofnode_path("/config");
 	if (!ofnode_valid(node)) {
 		debug("%s: no /config node?\n", __func__);
@@ -419,18 +425,14 @@ static int board_check_usb_power(void)
 
 	return 0;
 }
-#endif /* CONFIG_ADC */
 
 static void sysconf_init(void)
 {
-#ifndef CONFIG_TFABOOT
 	u8 *syscfg;
-#ifdef CONFIG_DM_REGULATOR
 	struct udevice *pwr_dev;
 	struct udevice *pwr_reg;
 	struct udevice *dev;
 	u32 otp = 0;
-#endif
 	int ret;
 	u32 bootr, val;
 
@@ -448,7 +450,6 @@ static void sysconf_init(void)
 	bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
 	writel(bootr, syscfg + SYSCFG_BOOTR);
 
-#ifdef CONFIG_DM_REGULATOR
 	/* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
 	 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
 	 * The customer will have to disable this for low frequencies
@@ -465,7 +466,7 @@ static void sysconf_init(void)
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
 					  DM_GET_DRIVER(stm32mp_pwr_pmic),
 					  &pwr_dev);
-	if (!ret) {
+	if (!ret && IS_ENABLED(CONFIG_DM_REGULATOR)) {
 		ret = uclass_get_device_by_driver(UCLASS_MISC,
 						  DM_GET_DRIVER(stm32mp_bsec),
 						  &dev);
@@ -502,7 +503,6 @@ static void sysconf_init(void)
 			debug("VDD unknown");
 		}
 	}
-#endif
 
 	/* activate automatic I/O compensation
 	 * warning: need to ensure CSI enabled and ready in clock driver
@@ -519,10 +519,8 @@ static void sysconf_init(void)
 	}
 
 	clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
-#endif
 }
 
-#ifdef CONFIG_DM_REGULATOR
 /* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */
 static int dk2_i2c1_fix(void)
 {
@@ -530,6 +528,9 @@ static int dk2_i2c1_fix(void)
 	struct gpio_desc hdmi, audio;
 	int ret = 0;
 
+	if (!IS_ENABLED(CONFIG_DM_REGULATOR))
+		return -ENODEV;
+
 	node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39");
 	if (!ofnode_valid(node)) {
 		pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__);
@@ -587,7 +588,6 @@ static bool board_is_dk2(void)
 
 	return false;
 }
-#endif
 
 static bool board_is_ev1(void)
 {
@@ -635,14 +635,14 @@ int board_init(void)
 	if (board_is_ev1())
 		board_ev1_init();
 
-#ifdef CONFIG_DM_REGULATOR
 	if (board_is_dk2())
 		dk2_i2c1_fix();
 
-	regulators_enable_boot_on(_DEBUG);
-#endif
+	if (IS_ENABLED(CONFIG_DM_REGULATOR))
+		regulators_enable_boot_on(_DEBUG);
 
-	sysconf_init();
+	if (!IS_ENABLED(CONFIG_TFABOOT))
+		sysconf_init();
 
 	if (CONFIG_IS_ENABLED(LED))
 		led_default_state();
@@ -654,52 +654,50 @@ int board_init(void)
 
 int board_late_init(void)
 {
-#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 	const void *fdt_compat;
 	int fdt_compat_len;
 	int ret;
 	u32 otp;
 	struct udevice *dev;
 	char buf[10];
+	char dtb_name[256];
+	int buf_len;
+
+	if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) {
+		fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
+					 &fdt_compat_len);
+		if (fdt_compat && fdt_compat_len) {
+			if (strncmp(fdt_compat, "st,", 3) != 0) {
+				env_set("board_name", fdt_compat);
+			} else {
+				env_set("board_name", fdt_compat + 3);
 
-	fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
-				 &fdt_compat_len);
-	if (fdt_compat && fdt_compat_len) {
-		if (strncmp(fdt_compat, "st,", 3) != 0) {
-			env_set("board_name", fdt_compat);
-		} else {
-			char dtb_name[256];
-			int buf_len = sizeof(dtb_name);
+				buf_len = sizeof(dtb_name);
+				strncpy(dtb_name, fdt_compat + 3, buf_len);
+				buf_len -= strlen(fdt_compat + 3);
+				strncat(dtb_name, ".dtb", buf_len);
+				env_set("fdtfile", dtb_name);
+			}
+		}
+		ret = uclass_get_device_by_driver(UCLASS_MISC,
+						  DM_GET_DRIVER(stm32mp_bsec),
+						  &dev);
 
-			env_set("board_name", fdt_compat + 3);
+		if (!ret)
+			ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
+					&otp, sizeof(otp));
+		if (ret > 0 && otp) {
+			snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
+			env_set("board_id", buf);
 
-			strncpy(dtb_name, fdt_compat + 3, buf_len);
-			buf_len -= strlen(fdt_compat + 3);
-			strncat(dtb_name, ".dtb", buf_len);
-			env_set("fdtfile", dtb_name);
+			snprintf(buf, sizeof(buf), "0x%04x",
+				 ((otp >> 8) & 0xF) - 1 + 0xA);
+			env_set("board_rev", buf);
 		}
 	}
-	ret = uclass_get_device_by_driver(UCLASS_MISC,
-					  DM_GET_DRIVER(stm32mp_bsec),
-					  &dev);
 
-	if (!ret)
-		ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
-				&otp, sizeof(otp));
-	if (ret > 0 && otp) {
-		snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
-		env_set("board_id", buf);
-
-		snprintf(buf, sizeof(buf), "0x%04x",
-			 ((otp >> 8) & 0xF) - 1 + 0xA);
-		env_set("board_rev", buf);
-	}
-#endif
-
-#ifdef CONFIG_ADC
 	/* for DK1/DK2 boards */
 	board_check_usb_power();
-#endif /* CONFIG_ADC */
 
 	return 0;
 }
@@ -787,31 +785,33 @@ enum env_location env_get_location(enum env_operation op, int prio)
 		return ENVL_UNKNOWN;
 
 	switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
-#if CONFIG_IS_ENABLED(ENV_IS_IN_MMC)
-	case BOOT_FLASH_SD:
-	case BOOT_FLASH_EMMC:
-		return ENVL_MMC;
-#endif
-#if CONFIG_IS_ENABLED(ENV_IS_IN_EXT4)
 	case BOOT_FLASH_SD:
 	case BOOT_FLASH_EMMC:
-		return ENVL_EXT4;
-#endif
-#if CONFIG_IS_ENABLED(ENV_IS_IN_UBI)
+		if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC))
+			return ENVL_MMC;
+		else if (CONFIG_IS_ENABLED(ENV_IS_IN_EXT4))
+			return ENVL_EXT4;
+		else
+			return ENVL_NOWHERE;
+
 	case BOOT_FLASH_NAND:
 	case BOOT_FLASH_SPINAND:
-		return ENVL_UBI;
-#endif
-#if CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH)
+		if (CONFIG_IS_ENABLED(ENV_IS_IN_UBI))
+			return ENVL_UBI;
+		else
+			return ENVL_NOWHERE;
+
 	case BOOT_FLASH_NOR:
-		return ENVL_SPI_FLASH;
-#endif
+		if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH))
+			return ENVL_SPI_FLASH;
+		else
+			return ENVL_NOWHERE;
+
 	default:
 		return ENVL_NOWHERE;
 	}
 }
 
-#if defined(CONFIG_ENV_IS_IN_EXT4)
 const char *env_ext4_get_intf(void)
 {
 	u32 bootmode = get_bootmode();
@@ -832,28 +832,25 @@ const char *env_ext4_get_dev_part(void)
 
 	return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
 }
-#endif
-
-#if defined(CONFIG_ENV_IS_IN_MMC)
 int mmc_get_env_dev(void)
 {
 	u32 bootmode = get_bootmode();
 
 	return (bootmode & TAMP_BOOT_INSTANCE_MASK) - 1;
 }
-#endif
 
 #if defined(CONFIG_OF_BOARD_SETUP)
 int ft_board_setup(void *blob, struct bd_info *bd)
 {
-#ifdef CONFIG_FDT_FIXUP_PARTITIONS
-	struct node_info nodes[] = {
+	static const struct node_info nodes[] = {
 		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_NOR,  },
 		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_SPINAND},
 		{ "st,stm32mp15-fmc2",		MTD_DEV_TYPE_NAND, },
+		{ "st,stm32mp1-fmc2-nfc",	MTD_DEV_TYPE_NAND, },
 	};
-	fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
-#endif
+
+	if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS))
+		fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 
 	return 0;
 }

+ 1 - 0
configs/stm32mp15_basic_defconfig

@@ -88,6 +88,7 @@ CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y

+ 1 - 0
configs/stm32mp15_dhcom_basic_defconfig

@@ -57,6 +57,7 @@ CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
 # CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_OF_LIST="stm32mp15xx-dhcom-pdk2 stm32mp15xx-dhcom-drc02"
 CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-names interrupts-extended interrupt-controller \\\#interrupt-cells interrupt-parent dmas dma-names assigned-clocks assigned-clock-rates assigned-clock-parents hwlocks"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_BUS=y

+ 1 - 0
configs/stm32mp15_trusted_defconfig

@@ -68,6 +68,7 @@ CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y

+ 9 - 0
drivers/memory/Kconfig

@@ -4,6 +4,15 @@
 
 menu "Memory Controller drivers"
 
+config STM32_FMC2_EBI
+	bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
+	depends on ARCH_STM32MP
+	help
+	  Select this option to enable the STM32 FMC2 External Bus Interface
+	  controller. This driver configures the transactions with external
+	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
+	  SOCs containing the FMC2 External Bus Interface.
+
 config TI_AEMIF
 	tristate "Texas Instruments AEMIF driver"
 	depends on ARCH_KEYSTONE

+ 1 - 0
drivers/memory/Makefile

@@ -1,2 +1,3 @@
 
+obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
 obj-$(CONFIG_TI_AEMIF) += ti-aemif.o

+ 1056 - 0
drivers/memory/stm32-fmc2-ebi.c

@@ -0,0 +1,1056 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <reset.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1			0x0
+#define FMC2_BTR1			0x4
+#define FMC2_BCR(x)			((x) * 0x8 + FMC2_BCR1)
+#define FMC2_BTR(x)			((x) * 0x8 + FMC2_BTR1)
+#define FMC2_PCSCNTR			0x20
+#define FMC2_BWTR1			0x104
+#define FMC2_BWTR(x)			((x) * 0x8 + FMC2_BWTR1)
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_CCLKEN		BIT(20)
+#define FMC2_BCR1_FMC2EN		BIT(31)
+
+/* Register: FMC2_BCRx */
+#define FMC2_BCR_MBKEN			BIT(0)
+#define FMC2_BCR_MUXEN			BIT(1)
+#define FMC2_BCR_MTYP			GENMASK(3, 2)
+#define FMC2_BCR_MWID			GENMASK(5, 4)
+#define FMC2_BCR_FACCEN			BIT(6)
+#define FMC2_BCR_BURSTEN		BIT(8)
+#define FMC2_BCR_WAITPOL		BIT(9)
+#define FMC2_BCR_WAITCFG		BIT(11)
+#define FMC2_BCR_WREN			BIT(12)
+#define FMC2_BCR_WAITEN			BIT(13)
+#define FMC2_BCR_EXTMOD			BIT(14)
+#define FMC2_BCR_ASYNCWAIT		BIT(15)
+#define FMC2_BCR_CPSIZE			GENMASK(18, 16)
+#define FMC2_BCR_CBURSTRW		BIT(19)
+#define FMC2_BCR_NBLSET			GENMASK(23, 22)
+
+/* Register: FMC2_BTRx/FMC2_BWTRx */
+#define FMC2_BXTR_ADDSET		GENMASK(3, 0)
+#define FMC2_BXTR_ADDHLD		GENMASK(7, 4)
+#define FMC2_BXTR_DATAST		GENMASK(15, 8)
+#define FMC2_BXTR_BUSTURN		GENMASK(19, 16)
+#define FMC2_BTR_CLKDIV			GENMASK(23, 20)
+#define FMC2_BTR_DATLAT			GENMASK(27, 24)
+#define FMC2_BXTR_ACCMOD		GENMASK(29, 28)
+#define FMC2_BXTR_DATAHLD		GENMASK(31, 30)
+
+/* Register: FMC2_PCSCNTR */
+#define FMC2_PCSCNTR_CSCOUNT		GENMASK(15, 0)
+#define FMC2_PCSCNTR_CNTBEN(x)		BIT((x) + 16)
+
+#define FMC2_MAX_EBI_CE			4
+#define FMC2_MAX_BANKS			5
+
+#define FMC2_BCR_CPSIZE_0		0x0
+#define FMC2_BCR_CPSIZE_128		0x1
+#define FMC2_BCR_CPSIZE_256		0x2
+#define FMC2_BCR_CPSIZE_512		0x3
+#define FMC2_BCR_CPSIZE_1024		0x4
+
+#define FMC2_BCR_MWID_8			0x0
+#define FMC2_BCR_MWID_16		0x1
+
+#define FMC2_BCR_MTYP_SRAM		0x0
+#define FMC2_BCR_MTYP_PSRAM		0x1
+#define FMC2_BCR_MTYP_NOR		0x2
+
+#define FMC2_BXTR_EXTMOD_A		0x0
+#define FMC2_BXTR_EXTMOD_B		0x1
+#define FMC2_BXTR_EXTMOD_C		0x2
+#define FMC2_BXTR_EXTMOD_D		0x3
+
+#define FMC2_BCR_NBLSET_MAX		0x3
+#define FMC2_BXTR_ADDSET_MAX		0xf
+#define FMC2_BXTR_ADDHLD_MAX		0xf
+#define FMC2_BXTR_DATAST_MAX		0xff
+#define FMC2_BXTR_BUSTURN_MAX		0xf
+#define FMC2_BXTR_DATAHLD_MAX		0x3
+#define FMC2_BTR_CLKDIV_MAX		0xf
+#define FMC2_BTR_DATLAT_MAX		0xf
+#define FMC2_PCSCNTR_CSCOUNT_MAX	0xff
+
+#define FMC2_NSEC_PER_SEC		1000000000L
+
+enum stm32_fmc2_ebi_bank {
+	FMC2_EBI1 = 0,
+	FMC2_EBI2,
+	FMC2_EBI3,
+	FMC2_EBI4,
+	FMC2_NAND
+};
+
+enum stm32_fmc2_ebi_register_type {
+	FMC2_REG_BCR = 1,
+	FMC2_REG_BTR,
+	FMC2_REG_BWTR,
+	FMC2_REG_PCSCNTR
+};
+
+enum stm32_fmc2_ebi_transaction_type {
+	FMC2_ASYNC_MODE_1_SRAM = 0,
+	FMC2_ASYNC_MODE_1_PSRAM,
+	FMC2_ASYNC_MODE_A_SRAM,
+	FMC2_ASYNC_MODE_A_PSRAM,
+	FMC2_ASYNC_MODE_2_NOR,
+	FMC2_ASYNC_MODE_B_NOR,
+	FMC2_ASYNC_MODE_C_NOR,
+	FMC2_ASYNC_MODE_D_NOR,
+	FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
+	FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
+	FMC2_SYNC_READ_SYNC_WRITE_NOR,
+	FMC2_SYNC_READ_ASYNC_WRITE_NOR
+};
+
+enum stm32_fmc2_ebi_buswidth {
+	FMC2_BUSWIDTH_8 = 8,
+	FMC2_BUSWIDTH_16 = 16
+};
+
+enum stm32_fmc2_ebi_cpsize {
+	FMC2_CPSIZE_0 = 0,
+	FMC2_CPSIZE_128 = 128,
+	FMC2_CPSIZE_256 = 256,
+	FMC2_CPSIZE_512 = 512,
+	FMC2_CPSIZE_1024 = 1024
+};
+
+struct stm32_fmc2_ebi {
+	struct clk clk;
+	fdt_addr_t io_base;
+	u8 bank_assigned;
+};
+
+/*
+ * struct stm32_fmc2_prop - STM32 FMC2 EBI property
+ * @name: the device tree binding name of the property
+ * @bprop: indicate that it is a boolean property
+ * @mprop: indicate that it is a mandatory property
+ * @reg_type: the register that have to be modified
+ * @reg_mask: the bit that have to be modified in the selected register
+ *            in case of it is a boolean property
+ * @reset_val: the default value that have to be set in case the property
+ *             has not been defined in the device tree
+ * @check: this callback ckecks that the property is compliant with the
+ *         transaction type selected
+ * @calculate: this callback is called to calculate for exemple a timing
+ *             set in nanoseconds in the device tree in clock cycles or in
+ *             clock period
+ * @set: this callback applies the values in the registers
+ */
+struct stm32_fmc2_prop {
+	const char *name;
+	bool bprop;
+	bool mprop;
+	int reg_type;
+	u32 reg_mask;
+	u32 reset_val;
+	int (*check)(struct stm32_fmc2_ebi *ebi,
+		     const struct stm32_fmc2_prop *prop, int cs);
+	u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
+	int (*set)(struct stm32_fmc2_ebi *ebi,
+		   const struct stm32_fmc2_prop *prop,
+		   int cs, u32 setup);
+};
+
+static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
+				    const struct stm32_fmc2_prop *prop,
+				    int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+	if (bcr & FMC2_BCR_MTYP)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
+					const struct stm32_fmc2_prop *prop,
+					int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+
+	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+	if (bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+	if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+
+	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
+					     const struct stm32_fmc2_prop *prop,
+					     int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+		   readl(ebi->io_base + FMC2_BWTR(cs)) :
+		   readl(ebi->io_base + FMC2_BTR(cs));
+	u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+
+	if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
+	    ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
+
+	if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs)
+{
+	if (cs)
+		return -EINVAL;
+
+	return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
+					     int cs, u32 setup)
+{
+	unsigned long hclk = clk_get_rate(&ebi->clk);
+	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
+
+	return DIV_ROUND_UP(setup * 1000, hclkp);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
+					   int cs, u32 setup)
+{
+	u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
+	u32 bcr = readl(ebi->io_base + FMC2_BCR1);
+	u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
+		  readl(ebi->io_base + FMC2_BTR1) :
+		  readl(ebi->io_base + FMC2_BTR(cs));
+	u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
+
+	return DIV_ROUND_UP(nb_clk_cycles, clk_period);
+}
+
+static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
+{
+	switch (reg_type) {
+	case FMC2_REG_BCR:
+		*reg = FMC2_BCR(cs);
+		break;
+	case FMC2_REG_BTR:
+		*reg = FMC2_BTR(cs);
+		break;
+	case FMC2_REG_BWTR:
+		*reg = FMC2_BWTR(cs);
+		break;
+	case FMC2_REG_PCSCNTR:
+		*reg = FMC2_PCSCNTR;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
+					const struct stm32_fmc2_prop *prop,
+					int cs, u32 setup)
+{
+	u32 reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	clrsetbits_le32(ebi->io_base + reg, prop->reg_mask,
+			setup ? prop->reg_mask : 0);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 bcr_mask, bcr = FMC2_BCR_WREN;
+	u32 btr_mask, btr = 0;
+	u32 bwtr_mask, bwtr = 0;
+
+	bwtr_mask = FMC2_BXTR_ACCMOD;
+	btr_mask = FMC2_BXTR_ACCMOD;
+	bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
+		   FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
+		   FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
+
+	switch (setup) {
+	case FMC2_ASYNC_MODE_1_SRAM:
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+		/*
+		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		break;
+	case FMC2_ASYNC_MODE_1_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		break;
+	case FMC2_ASYNC_MODE_A_SRAM:
+		/*
+		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+		bcr |= FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		break;
+	case FMC2_ASYNC_MODE_A_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		break;
+	case FMC2_ASYNC_MODE_2_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN;
+		break;
+	case FMC2_ASYNC_MODE_B_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+		break;
+	case FMC2_ASYNC_MODE_C_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+		break;
+	case FMC2_ASYNC_MODE_D_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+		break;
+	case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+		break;
+	case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_BURSTEN;
+		break;
+	case FMC2_SYNC_READ_SYNC_WRITE_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+		break;
+	case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
+		break;
+	default:
+		/* Type of transaction not supported */
+		return -EINVAL;
+	}
+
+	if (bcr & FMC2_BCR_EXTMOD)
+		clrsetbits_le32(ebi->io_base + FMC2_BWTR(cs),
+				bwtr_mask, bwtr);
+	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), btr_mask, btr);
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), bcr_mask, bcr);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs, u32 setup)
+{
+	u32 val;
+
+	switch (setup) {
+	case FMC2_BUSWIDTH_8:
+		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
+		break;
+	case FMC2_BUSWIDTH_16:
+		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
+		break;
+	default:
+		/* Buswidth not supported */
+		return -EINVAL;
+	}
+
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MWID, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs, u32 setup)
+{
+	u32 val;
+
+	switch (setup) {
+	case FMC2_CPSIZE_0:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
+		break;
+	case FMC2_CPSIZE_128:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
+		break;
+	case FMC2_CPSIZE_256:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
+		break;
+	case FMC2_CPSIZE_512:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
+		break;
+	case FMC2_CPSIZE_1024:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
+		break;
+	default:
+		/* Cpsize not supported */
+		return -EINVAL;
+	}
+
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs, u32 setup)
+{
+	u32 val;
+
+	val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
+	val = FIELD_PREP(FMC2_BCR_NBLSET, val);
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs, u32 setup)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+		   readl(ebi->io_base + FMC2_BWTR(cs)) :
+		   readl(ebi->io_base + FMC2_BTR(cs));
+	u32 reg, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
+		val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
+	else
+		val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
+	val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDSET, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
+	val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDHLD, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
+	val = FIELD_PREP(FMC2_BXTR_DATAST, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAST, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi,
+					     const struct stm32_fmc2_prop *prop,
+					     int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
+	val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_BUSTURN, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi,
+					const struct stm32_fmc2_prop *prop,
+					int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	if (prop->reg_type == FMC2_REG_BWTR)
+		val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
+	else
+		val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
+	val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAHLD, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 val;
+
+	val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
+	val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
+	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs, u32 setup)
+{
+	u32 val;
+
+	val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0;
+	val = FIELD_PREP(FMC2_BTR_DATLAT, val);
+	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs, u32 setup)
+{
+	u32 old_val, new_val, pcscntr;
+
+	if (setup < 1)
+		return 0;
+
+	pcscntr = readl(ebi->io_base + FMC2_PCSCNTR);
+
+	/* Enable counter for the bank */
+	setbits_le32(ebi->io_base + FMC2_PCSCNTR, FMC2_PCSCNTR_CNTBEN(cs));
+
+	new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
+	old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
+	if (old_val && new_val > old_val)
+		/* Keep current counter value */
+		return 0;
+
+	new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
+	clrsetbits_le32(ebi->io_base + FMC2_PCSCNTR,
+			FMC2_PCSCNTR_CSCOUNT, new_val);
+
+	return 0;
+}
+
+static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
+	/* st,fmc2-ebi-cs-trans-type must be the first property */
+	{
+		.name = "st,fmc2-ebi-cs-transaction-type",
+		.mprop = true,
+		.set = stm32_fmc2_ebi_set_trans_type,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-cclk-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR1_CCLKEN,
+		.check = stm32_fmc2_ebi_check_cclk,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-mux-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_MUXEN,
+		.check = stm32_fmc2_ebi_check_mux,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-buswidth",
+		.reset_val = FMC2_BUSWIDTH_16,
+		.set = stm32_fmc2_ebi_set_buswidth,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-waitpol-high",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITPOL,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-waitcfg-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITCFG,
+		.check = stm32_fmc2_ebi_check_waitcfg,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-wait-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITEN,
+		.check = stm32_fmc2_ebi_check_sync_trans,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-asyncwait-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_ASYNCWAIT,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-cpsize",
+		.check = stm32_fmc2_ebi_check_cpsize,
+		.set = stm32_fmc2_ebi_set_cpsize,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bl_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-address-setup-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_ADDSET_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-address-hold-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_ADDHLD_MAX,
+		.check = stm32_fmc2_ebi_check_address_hold,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-data-setup-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_DATAST_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-bus-turnaround-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bus_turnaround,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-data-hold-ns",
+		.reg_type = FMC2_REG_BTR,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-clk-period-ns",
+		.reset_val = FMC2_BTR_CLKDIV_MAX + 1,
+		.check = stm32_fmc2_ebi_check_clk_period,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_clk_period,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-data-latency-ns",
+		.check = stm32_fmc2_ebi_check_sync_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clk_period,
+		.set = stm32_fmc2_ebi_set_data_latency,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-address-setup-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_ADDSET_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-address-hold-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_ADDHLD_MAX,
+		.check = stm32_fmc2_ebi_check_address_hold,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-data-setup-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_DATAST_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bus_turnaround,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-data-hold-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-max-low-pulse-ns",
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_max_low_pulse,
+	},
+};
+
+static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
+				     ofnode node,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs)
+{
+	u32 setup = 0;
+
+	if (!prop->set) {
+		pr_err("property %s is not well defined\n", prop->name);
+		return -EINVAL;
+	}
+
+	if (prop->check && prop->check(ebi, prop, cs))
+		/* Skip this property */
+		return 0;
+
+	if (prop->bprop) {
+		bool bprop;
+
+		bprop = ofnode_read_bool(node, prop->name);
+		if (prop->mprop && !bprop) {
+			pr_err("mandatory property %s not defined in the device tree\n",
+			       prop->name);
+			return -EINVAL;
+		}
+
+		if (bprop)
+			setup = 1;
+	} else {
+		u32 val;
+		int ret;
+
+		ret = ofnode_read_u32(node, prop->name, &val);
+		if (prop->mprop && ret) {
+			pr_err("mandatory property %s not defined in the device tree\n",
+			       prop->name);
+			return ret;
+		}
+
+		if (ret)
+			setup = prop->reset_val;
+		else if (prop->calculate)
+			setup = prop->calculate(ebi, cs, val);
+		else
+			setup = val;
+	}
+
+	return prop->set(ebi, prop, cs, setup);
+}
+
+static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs)
+{
+	setbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
+}
+
+static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
+{
+	clrbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
+}
+
+/* NWAIT signal can not be connected to EBI controller and NAND controller */
+static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
+{
+	unsigned int cs;
+	u32 bcr;
+
+	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+		if (!(ebi->bank_assigned & BIT(cs)))
+			continue;
+
+		bcr = readl(ebi->io_base + FMC2_BCR(cs));
+		if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
+		    ebi->bank_assigned & BIT(FMC2_NAND))
+			return true;
+	}
+
+	return false;
+}
+
+static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
+{
+	setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
+}
+
+static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi,
+				   ofnode node, u32 cs)
+{
+	unsigned int i;
+	int ret;
+
+	stm32_fmc2_ebi_disable_bank(ebi, cs);
+
+	for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) {
+		const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i];
+
+		ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs);
+		if (ret) {
+			pr_err("property %s could not be set: %d\n",
+			       p->name, ret);
+			return ret;
+		}
+	}
+
+	stm32_fmc2_ebi_enable_bank(ebi, cs);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_parse_dt(struct udevice *dev,
+				   struct stm32_fmc2_ebi *ebi)
+{
+	ofnode child;
+	bool child_found = false;
+	u32 bank;
+	int ret;
+
+	dev_for_each_subnode(child, dev) {
+		ret = ofnode_read_u32(child, "reg", &bank);
+		if (ret) {
+			pr_err("could not retrieve reg property: %d\n", ret);
+			return ret;
+		}
+
+		if (bank >= FMC2_MAX_BANKS) {
+			pr_err("invalid reg value: %d\n", bank);
+			return -EINVAL;
+		}
+
+		if (ebi->bank_assigned & BIT(bank)) {
+			pr_err("bank already assigned: %d\n", bank);
+			return -EINVAL;
+		}
+
+		if (bank < FMC2_MAX_EBI_CE) {
+			ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
+			if (ret) {
+				pr_err("setup chip select %d failed: %d\n",
+				       bank, ret);
+				return ret;
+			}
+		}
+
+		ebi->bank_assigned |= BIT(bank);
+		child_found = true;
+	}
+
+	if (!child_found) {
+		pr_warn("no subnodes found, disable the driver.\n");
+		return -ENODEV;
+	}
+
+	if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) {
+		pr_err("NWAIT signal connected to EBI and NAND controllers\n");
+		return -EINVAL;
+	}
+
+	stm32_fmc2_ebi_enable(ebi);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_probe(struct udevice *dev)
+{
+	struct stm32_fmc2_ebi *ebi = dev_get_priv(dev);
+	struct reset_ctl reset;
+	int ret;
+
+	ebi->io_base = dev_read_addr(dev);
+	if (ebi->io_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	ret = clk_get_by_index(dev, 0, &ebi->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&ebi->clk);
+	if (ret)
+		return ret;
+
+	ret = reset_get_by_index(dev, 0, &reset);
+	if (!ret) {
+		reset_assert(&reset);
+		udelay(2);
+		reset_deassert(&reset);
+	}
+
+	return stm32_fmc2_ebi_parse_dt(dev, ebi);
+}
+
+static const struct udevice_id stm32_fmc2_ebi_match[] = {
+	{.compatible = "st,stm32mp1-fmc2-ebi"},
+	{ /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(stm32_fmc2_ebi) = {
+	.name = "stm32_fmc2_ebi",
+	.id = UCLASS_NOP,
+	.of_match = stm32_fmc2_ebi_match,
+	.probe = stm32_fmc2_ebi_probe,
+	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_ebi),
+	.bind = dm_scan_fdt_dev,
+};

+ 242 - 257
drivers/mtd/nand/raw/stm32_fmc2_nand.c

@@ -10,6 +10,7 @@
 #include <log.h>
 #include <nand.h>
 #include <reset.h>
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -60,20 +61,16 @@
 /* Register: FMC2_PCR */
 #define FMC2_PCR_PWAITEN		BIT(1)
 #define FMC2_PCR_PBKEN			BIT(2)
-#define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
-#define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
+#define FMC2_PCR_PWID			GENMASK(5, 4)
 #define FMC2_PCR_PWID_BUSWIDTH_8	0
 #define FMC2_PCR_PWID_BUSWIDTH_16	1
 #define FMC2_PCR_ECCEN			BIT(6)
 #define FMC2_PCR_ECCALG			BIT(8)
-#define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
-#define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR			GENMASK(12, 9)
 #define FMC2_PCR_TCLR_DEFAULT		0xf
-#define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
-#define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
+#define FMC2_PCR_TAR			GENMASK(16, 13)
 #define FMC2_PCR_TAR_DEFAULT		0xf
-#define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
-#define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS			GENMASK(19, 17)
 #define FMC2_PCR_ECCSS_512		1
 #define FMC2_PCR_ECCSS_2048		3
 #define FMC2_PCR_BCHECC			BIT(24)
@@ -83,17 +80,17 @@
 #define FMC2_SR_NWRF			BIT(6)
 
 /* Register: FMC2_PMEM */
-#define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
-#define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
-#define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
-#define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
+#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
+#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
+#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
 #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
 
 /* Register: FMC2_PATT */
-#define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
-#define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
-#define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
-#define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PATT_ATTSET		GENMASK(7, 0)
+#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
+#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
+#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
 #define FMC2_PATT_DEFAULT		0x0a0a0a0a
 
 /* Register: FMC2_BCHISR */
@@ -106,31 +103,28 @@
 /* Register: FMC2_BCHDSR0 */
 #define FMC2_BCHDSR0_DUE		BIT(0)
 #define FMC2_BCHDSR0_DEF		BIT(1)
-#define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
-#define FMC2_BCHDSR0_DEN_SHIFT		4
+#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
 
 /* Register: FMC2_BCHDSR1 */
-#define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR1_EBP2_SHIFT		16
+#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR2 */
-#define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR2_EBP4_SHIFT		16
+#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR3 */
-#define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR3_EBP6_SHIFT		16
+#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR4 */
-#define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR4_EBP8_SHIFT		16
+#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
 
 #define FMC2_NSEC_PER_SEC		1000000000L
 
+#define FMC2_TIMEOUT_5S			5000000
+
 enum stm32_fmc2_ecc {
 	FMC2_ECC_HAM = 1,
 	FMC2_ECC_BCH4 = 4,
@@ -164,10 +158,10 @@ struct stm32_fmc2_nfc {
 	struct nand_hw_control base;
 	struct stm32_fmc2_nand nand;
 	struct nand_ecclayout ecclayout;
-	void __iomem *io_base;
-	void __iomem *data_base[FMC2_MAX_CE];
-	void __iomem *cmd_base[FMC2_MAX_CE];
-	void __iomem *addr_base[FMC2_MAX_CE];
+	fdt_addr_t io_base;
+	fdt_addr_t data_base[FMC2_MAX_CE];
+	fdt_addr_t cmd_base[FMC2_MAX_CE];
+	fdt_addr_t addr_base[FMC2_MAX_CE];
 	struct clk clk;
 
 	u8 cs_assigned;
@@ -179,47 +173,42 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
 	return container_of(base, struct stm32_fmc2_nfc, base);
 }
 
-/* Timings configuration */
-static void stm32_fmc2_timings_init(struct nand_chip *chip)
+static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR_MASK;
-	pcr |= FMC2_PCR_TCLR(timings->tclr);
-	pcr &= ~FMC2_PCR_TAR_MASK;
-	pcr |= FMC2_PCR_TAR(timings->tar);
+	clrsetbits_le32(nfc->io_base + FMC2_PCR,
+			FMC2_PCR_TCLR | FMC2_PCR_TAR,
+			FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
+			FIELD_PREP(FMC2_PCR_TAR, timings->tar));
 
 	/* Set tset/twait/thold/thiz timings in common bank */
-	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
-	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
-	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
-	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
+	writel(pmem, nfc->io_base + FMC2_PMEM);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
-	patt = FMC2_PATT_ATTSET(timings->tset_att);
-	patt |= FMC2_PATT_ATTWAIT(timings->twait);
-	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
-	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
-
-	writel(pcr, fmc2->io_base + FMC2_PCR);
-	writel(pmem, fmc2->io_base + FMC2_PMEM);
-	writel(patt, fmc2->io_base + FMC2_PATT);
+	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
+	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
+	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
+	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
+	writel(patt, nfc->io_base + FMC2_PATT);
 }
 
-/* Controller configuration */
-static void stm32_fmc2_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	u32 pcr = 0, pcr_mask;
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
-	pcr &= ~FMC2_PCR_ECCALG;
-	pcr &= ~FMC2_PCR_BCHECC;
+	pcr_mask = FMC2_PCR_ECCALG;
+	pcr_mask |= FMC2_PCR_BCHECC;
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		pcr |= FMC2_PCR_ECCALG;
 		pcr |= FMC2_PCR_BCHECC;
@@ -228,111 +217,95 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
 	}
 
 	/* Set buswidth */
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr_mask |= FMC2_PCR_PWID;
 	if (chip->options & NAND_BUSWIDTH_16)
-		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 
 	/* Set ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS_MASK;
-	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+	pcr_mask |= FMC2_PCR_ECCSS;
+	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
 }
 
-/* Select target */
-static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
+static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 
 	if (chipnr < 0 || chipnr >= nand->ncs)
 		return;
 
-	if (nand->cs_used[chipnr] == fmc2->cs_sel)
+	if (nand->cs_used[chipnr] == nfc->cs_sel)
 		return;
 
-	fmc2->cs_sel = nand->cs_used[chipnr];
-	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
-	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
-
-	/* FMC2 setup routine */
-	stm32_fmc2_setup(chip);
+	nfc->cs_sel = nand->cs_used[chipnr];
+	chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
+	chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
 
-	/* Apply timings */
-	stm32_fmc2_timings_init(chip);
+	stm32_fmc2_nfc_setup(chip);
+	stm32_fmc2_nfc_timings_init(chip);
 }
 
-/* Set bus width to 16-bit or 8-bit */
-static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
+					   bool set)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 pcr;
 
-	pcr &= ~FMC2_PCR_PWID_MASK;
-	if (set)
-		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
+		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
+
+	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
 }
 
-/* Enable/disable ECC */
-static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
-
-	pcr &= ~FMC2_PCR_ECCEN;
-	if (enable)
-		pcr |= FMC2_PCR_ECCEN;
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
+			enable ? FMC2_PCR_ECCEN : 0);
 }
 
-/* Clear irq sources in case of bch is used */
-static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
+	writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
 }
 
-/* Send command and address cycles */
-static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
-				unsigned int ctrl)
+static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
+				    unsigned int ctrl)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
 
 	if (ctrl & NAND_CLE) {
-		writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
+		writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
 		return;
 	}
 
-	writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
+	writeb(cmd, nfc->addr_base[nfc->cs_sel]);
 }
 
 /*
  * Enable ECC logic and reset syndrome/parity bits previously calculated
  * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
  */
-static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
+static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+		clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
+				mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
 
-		if (mode == NAND_ECC_WRITE)
-			pcr |= FMC2_PCR_WEN;
-		else
-			pcr &= ~FMC2_PCR_WEN;
-		writel(pcr, fmc2->io_base + FMC2_PCR);
-
-		stm32_fmc2_clear_bch_irq(fmc2);
+		stm32_fmc2_nfc_clear_bch_irq(nfc);
 	}
 
-	stm32_fmc2_set_ecc(fmc2, true);
+	stm32_fmc2_nfc_set_ecc(nfc, true);
 }
 
 /*
@@ -340,35 +313,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
  * ECC is 3 bytes for 512 bytes of data (supports error correction up to
  * max of 1-bit)
  */
-static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
-				    u8 *ecc)
+static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
+					u8 *ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 heccr, sr;
 	int ret;
 
-	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
-				 sr & FMC2_SR_NWRF, 10000);
+	ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
+				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Ham timeout\n");
 		return ret;
 	}
 
-	heccr = readl(fmc2->io_base + FMC2_HECCR);
+	heccr = readl(nfc->io_base + FMC2_HECCR);
 
 	ecc[0] = heccr;
 	ecc[1] = heccr >> 8;
 	ecc[2] = heccr >> 16;
 
-	/* Disable ecc */
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	return 0;
 }
 
-static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
-				  u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
 	u8 bit_position = 0, b0, b1, b2;
 	u32 byte_addr = 0, b;
@@ -425,30 +397,30 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
  * max of 4-bit/8-bit)
  */
 
-static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
-				    u8 *ecc)
+static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
+					u8 *ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 bchpbr, bchisr;
 	int ret;
 
 	/* Wait until the BCH code is ready */
-	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
-				 bchisr & FMC2_BCHISR_EPBRF, 10000);
+	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
+				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Bch timeout\n");
 		return ret;
 	}
 
 	/* Read parity bits */
-	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
+	bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
 	ecc[0] = bchpbr;
 	ecc[1] = bchpbr >> 8;
 	ecc[2] = bchpbr >> 16;
 	ecc[3] = bchpbr >> 24;
 
-	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
+	bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
 	ecc[4] = bchpbr;
 	ecc[5] = bchpbr >> 8;
 	ecc[6] = bchpbr >> 16;
@@ -456,49 +428,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		ecc[7] = bchpbr >> 24;
 
-		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
+		bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
 		ecc[8] = bchpbr;
 		ecc[9] = bchpbr >> 8;
 		ecc[10] = bchpbr >> 16;
 		ecc[11] = bchpbr >> 24;
 
-		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
+		bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
 		ecc[12] = bchpbr;
 	}
 
-	/* Disable ecc */
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	return 0;
 }
 
-/* BCH algorithm correction */
-static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
-				  u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
 	u16 pos[8];
 	int i, ret, den, eccsize = chip->ecc.size;
 	unsigned int nb_errs = 0;
 
 	/* Wait until the decoding error is ready */
-	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
-				 bchisr & FMC2_BCHISR_DERF, 10000);
+	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
+				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Bch timeout\n");
 		return ret;
 	}
 
-	bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
-	bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
-	bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
-	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
-	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
+	bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
+	bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
+	bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
+	bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
+	bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
 
-	/* Disable ECC */
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	/* No errors found */
 	if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
@@ -508,16 +477,16 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
 	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
 		return -EBADMSG;
 
-	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
-	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
-	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
-	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
-	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
-	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
-	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
-	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+	pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
+	pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
+	pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
+	pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
+	pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
+	pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
+	pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
+	pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
 
-	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
+	den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
 	for (i = 0; i < den; i++) {
 		if (pos[i] < eccsize * 8) {
 			__change_bit(pos[i], (unsigned long *)dat);
@@ -528,9 +497,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
 	return nb_errs;
 }
 
-static int stm32_fmc2_read_page(struct mtd_info *mtd,
-				struct nand_chip *chip, u8 *buf,
-				int oob_required, int page)
+static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
+				    struct nand_chip *chip, u8 *buf,
+				    int oob_required, int page)
 {
 	int i, s, stat, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -579,21 +548,19 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
 	return max_bitflips;
 }
 
-/* Controller initialization */
-static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
-	u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
 	/* Set CS used to undefined */
-	fmc2->cs_sel = -1;
+	nfc->cs_sel = -1;
 
 	/* Enable wait feature and nand flash memory bank */
 	pcr |= FMC2_PCR_PWAITEN;
 	pcr |= FMC2_PCR_PBKEN;
 
 	/* Set buswidth to 8 bits mode for identification */
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 
 	/* ECC logic is disabled */
 	pcr &= ~FMC2_PCR_ECCEN;
@@ -604,32 +571,31 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 	pcr &= ~FMC2_PCR_WEN;
 
 	/* Set default ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS_MASK;
-	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+	pcr &= ~FMC2_PCR_ECCSS;
+	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
 
 	/* Set default tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR_MASK;
-	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
-	pcr &= ~FMC2_PCR_TAR_MASK;
-	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+	pcr &= ~FMC2_PCR_TCLR;
+	pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
+	pcr &= ~FMC2_PCR_TAR;
+	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
 	/* Enable FMC2 controller */
-	bcr1 |= FMC2_BCR1_FMC2EN;
+	if (!has_parent)
+		setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
 
-	writel(bcr1, fmc2->io_base + FMC2_BCR1);
-	writel(pcr, fmc2->io_base + FMC2_PCR);
-	writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
-	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+	writel(pcr, nfc->io_base + FMC2_PCR);
+	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
+	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
 }
 
-/* Controller timings */
-static void stm32_fmc2_calc_timings(struct nand_chip *chip,
-				    const struct nand_sdr_timings *sdrt)
+static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
+					const struct nand_sdr_timings *sdrt)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *tims = &nand->timings;
-	unsigned long hclk = clk_get_rate(&fmc2->clk);
+	unsigned long hclk = clk_get_rate(&nfc->clk);
 	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
 	unsigned long timing, tar, tclr, thiz, twait;
 	unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -753,31 +719,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
 	tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
 }
 
-static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
-				      const struct nand_data_interface *conf)
+static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
+					  const struct nand_data_interface *cf)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	const struct nand_sdr_timings *sdrt;
 
-	sdrt = nand_get_sdr_timings(conf);
+	sdrt = nand_get_sdr_timings(cf);
 	if (IS_ERR(sdrt))
 		return PTR_ERR(sdrt);
 
 	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
 		return 0;
 
-	stm32_fmc2_calc_timings(chip, sdrt);
-
-	/* Apply timings */
-	stm32_fmc2_timings_init(chip);
+	stm32_fmc2_nfc_calc_timings(chip, sdrt);
+	stm32_fmc2_nfc_timings_init(chip);
 
 	return 0;
 }
 
-/* NAND callbacks setup */
-static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
 {
-	chip->ecc.hwctl = stm32_fmc2_hwctl;
+	chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
 
 	/*
 	 * Specific callbacks to read/write a page depending on
@@ -785,17 +748,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 	 */
 	if (chip->ecc.strength == FMC2_ECC_HAM) {
 		/* Hamming is used */
-		chip->ecc.calculate = stm32_fmc2_ham_calculate;
-		chip->ecc.correct = stm32_fmc2_ham_correct;
+		chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
+		chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
 		chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
 		return;
 	}
 
 	/* BCH is used */
-	chip->ecc.read_page = stm32_fmc2_read_page;
-	chip->ecc.calculate = stm32_fmc2_bch_calculate;
-	chip->ecc.correct = stm32_fmc2_bch_correct;
+	chip->ecc.read_page = stm32_fmc2_nfc_read_page;
+	chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
+	chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
 
 	if (chip->ecc.strength == FMC2_ECC_BCH8)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
@@ -803,8 +766,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
 }
 
-/* FMC2 caps */
-static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
 {
 	/* Hamming */
 	if (strength == FMC2_ECC_HAM)
@@ -818,15 +780,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
 	return 8;
 }
 
-NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
+NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
 		     FMC2_ECC_STEP_SIZE,
 		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
 
-/* FMC2 probe */
-static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
-				  ofnode node)
+static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
 {
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 	u32 cs[FMC2_MAX_CE];
 	int ret, i;
 
@@ -846,19 +806,19 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 	}
 
 	for (i = 0; i < nand->ncs; i++) {
-		if (cs[i] > FMC2_MAX_CE) {
+		if (cs[i] >= FMC2_MAX_CE) {
 			pr_err("Invalid reg value: %d\n",
 			       nand->cs_used[i]);
 			return -EINVAL;
 		}
 
-		if (fmc2->cs_assigned & BIT(cs[i])) {
+		if (nfc->cs_assigned & BIT(cs[i])) {
 			pr_err("Cs already assigned: %d\n",
 			       nand->cs_used[i]);
 			return -EINVAL;
 		}
 
-		fmc2->cs_assigned |= BIT(cs[i]);
+		nfc->cs_assigned |= BIT(cs[i]);
 		nand->cs_used[i] = cs[i];
 	}
 
@@ -867,8 +827,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 	return 0;
 }
 
-static int stm32_fmc2_parse_dt(struct udevice *dev,
-			       struct stm32_fmc2_nfc *fmc2)
+static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
+				   struct stm32_fmc2_nfc *nfc)
 {
 	ofnode child;
 	int ret, nchips = 0;
@@ -887,7 +847,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
 	}
 
 	dev_for_each_subnode(child, dev) {
-		ret = stm32_fmc2_parse_child(fmc2, child);
+		ret = stm32_fmc2_nfc_parse_child(nfc, child);
 		if (ret)
 			return ret;
 	}
@@ -895,69 +855,98 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
 	return 0;
 }
 
-static int stm32_fmc2_probe(struct udevice *dev)
+static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
 {
-	struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct udevice *pdev = dev_get_parent(dev);
+	struct udevice *cdev = NULL;
+	bool ebi_found = false;
+
+	if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
+						"st,stm32mp1-fmc2-ebi"))
+		ebi_found = true;
+
+	if (ofnode_device_is_compatible(dev_ofnode(dev),
+					"st,stm32mp1-fmc2-nfc")) {
+		if (ebi_found)
+			cdev = pdev;
+
+		return cdev;
+	}
+
+	if (!ebi_found)
+		cdev = dev;
+
+	return cdev;
+}
+
+static int stm32_fmc2_nfc_probe(struct udevice *dev)
+{
+	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 	struct nand_chip *chip = &nand->chip;
 	struct mtd_info *mtd = &chip->mtd;
 	struct nand_ecclayout *ecclayout;
-	struct resource resource;
+	struct udevice *cdev;
 	struct reset_ctl reset;
 	int oob_index, chip_cs, mem_region, ret;
 	unsigned int i;
+	int start_region = 0;
+	fdt_addr_t addr;
+
+	spin_lock_init(&nfc->controller.lock);
+	init_waitqueue_head(&nfc->controller.wq);
 
-	spin_lock_init(&fmc2->controller.lock);
-	init_waitqueue_head(&fmc2->controller.wq);
+	cdev = stm32_fmc2_nfc_get_cdev(dev);
+	if (!cdev)
+		return -EINVAL;
 
-	ret = stm32_fmc2_parse_dt(dev, fmc2);
+	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
 	if (ret)
 		return ret;
 
-	/* Get resources */
-	ret = dev_read_resource(dev, 0, &resource);
-	if (ret) {
-		pr_err("Resource io_base not found");
-		return ret;
-	}
-	fmc2->io_base = (void __iomem *)resource.start;
+	nfc->io_base = dev_read_addr(cdev);
+	if (nfc->io_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	if (dev == cdev)
+		start_region = 1;
 
-	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+	for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
 	     chip_cs++, mem_region += 3) {
-		if (!(fmc2->cs_assigned & BIT(chip_cs)))
+		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
 
-		ret = dev_read_resource(dev, mem_region, &resource);
-		if (ret) {
+		addr = dev_read_addr_index(dev, mem_region);
+		if (addr == FDT_ADDR_T_NONE) {
 			pr_err("Resource data_base not found for cs%d",
 			       chip_cs);
 			return ret;
 		}
-		fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->data_base[chip_cs] = addr;
 
-		ret = dev_read_resource(dev, mem_region + 1, &resource);
-		if (ret) {
+		addr = dev_read_addr_index(dev, mem_region + 1);
+		if (addr == FDT_ADDR_T_NONE) {
 			pr_err("Resource cmd_base not found for cs%d",
 			       chip_cs);
 			return ret;
 		}
-		fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->cmd_base[chip_cs] = addr;
 
-		ret = dev_read_resource(dev, mem_region + 2, &resource);
-		if (ret) {
+		addr = dev_read_addr_index(dev, mem_region + 2);
+		if (addr == FDT_ADDR_T_NONE) {
 			pr_err("Resource addr_base not found for cs%d",
 			       chip_cs);
 			return ret;
 		}
-		fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->addr_base[chip_cs] = addr;
 	}
 
 	/* Enable the clock */
-	ret = clk_get_by_index(dev, 0, &fmc2->clk);
+	ret = clk_get_by_index(cdev, 0, &nfc->clk);
 	if (ret)
 		return ret;
 
-	ret = clk_enable(&fmc2->clk);
+	ret = clk_enable(&nfc->clk);
 	if (ret)
 		return ret;
 
@@ -969,13 +958,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
 		reset_deassert(&reset);
 	}
 
-	/* FMC2 init routine */
-	stm32_fmc2_init(fmc2);
+	stm32_fmc2_nfc_init(nfc, dev != cdev);
 
-	chip->controller = &fmc2->base;
-	chip->select_chip = stm32_fmc2_select_chip;
-	chip->setup_data_interface = stm32_fmc2_setup_interface;
-	chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
+	chip->controller = &nfc->base;
+	chip->select_chip = stm32_fmc2_nfc_select_chip;
+	chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
+	chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
 	chip->chip_delay = FMC2_RB_DELAY_US;
 	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
 			 NAND_USE_BOUNCE_BUFFER;
@@ -985,7 +973,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	chip->ecc.size = FMC2_ECC_STEP_SIZE;
 	chip->ecc.strength = FMC2_ECC_BCH8;
 
-	/* Scan to find existence of the device */
 	ret = nand_scan_ident(mtd, nand->ncs, NULL);
 	if (ret)
 		return ret;
@@ -1002,7 +989,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
 		return -EINVAL;
 	}
 
-	ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
+	ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
 				  mtd->oobsize - FMC2_BBM_LEN);
 	if (ret) {
 		pr_err("No valid ECC settings set\n");
@@ -1012,11 +999,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
-	/* NAND callbacks setup */
-	stm32_fmc2_nand_callbacks_setup(chip);
+	stm32_fmc2_nfc_nand_callbacks_setup(chip);
 
 	/* Define ECC layout */
-	ecclayout = &fmc2->ecclayout;
+	ecclayout = &nfc->ecclayout;
 	ecclayout->eccbytes = chip->ecc.bytes *
 			      (mtd->writesize / chip->ecc.size);
 	oob_index = FMC2_BBM_LEN;
@@ -1026,11 +1012,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
 	chip->ecc.layout = ecclayout;
 
-	/* Configure bus width to 16-bit */
 	if (chip->options & NAND_BUSWIDTH_16)
-		stm32_fmc2_set_buswidth_16(fmc2, true);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
 
-	/* Scan the device to fill MTD data-structures */
 	ret = nand_scan_tail(mtd);
 	if (ret)
 		return ret;
@@ -1038,16 +1022,17 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	return nand_register(0, mtd);
 }
 
-static const struct udevice_id stm32_fmc2_match[] = {
+static const struct udevice_id stm32_fmc2_nfc_match[] = {
 	{ .compatible = "st,stm32mp15-fmc2" },
+	{ .compatible = "st,stm32mp1-fmc2-nfc" },
 	{ /* Sentinel */ }
 };
 
-U_BOOT_DRIVER(stm32_fmc2_nand) = {
-	.name = "stm32_fmc2_nand",
+U_BOOT_DRIVER(stm32_fmc2_nfc) = {
+	.name = "stm32_fmc2_nfc",
 	.id = UCLASS_MTD,
-	.of_match = stm32_fmc2_match,
-	.probe = stm32_fmc2_probe,
+	.of_match = stm32_fmc2_nfc_match,
+	.probe = stm32_fmc2_nfc_probe,
 	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
 };
 
@@ -1057,9 +1042,9 @@ void board_nand_init(void)
 	int ret;
 
 	ret = uclass_get_device_by_driver(UCLASS_MTD,
-					  DM_GET_DRIVER(stm32_fmc2_nand),
+					  DM_GET_DRIVER(stm32_fmc2_nfc),
 					  &dev);
 	if (ret && ret != -ENODEV)
-		pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
+		pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
 		       ret);
 }

+ 1 - 1
drivers/usb/host/dwc3-sti-glue.c

@@ -159,7 +159,7 @@ static int sti_dwc3_glue_bind(struct udevice *dev)
 			dwc3_node = node;
 	}
 
-	if (!ofnode_valid(node)) {
+	if (!ofnode_valid(dwc3_node)) {
 		pr_err("Can't find dwc3 subnode for %s\n", dev->name);
 		return -ENODEV;
 	}