Merge tag 'u-boot-stm32-20210618' of https://source.denx.de/u-boot/custodians/u-boot-stm into next

 - stm32mp157c-odyssey-som DT fixes
 - stm32_qspi: Fix short data write operation
 - dfu: set max_buf_size to erasesize also for NOR devices
 - Fixes ethernet clock property name for STM32MP1 board
 - STM32CubeProgrammer: various fixes
 - clk: cosmetic update for clk-uclass
diff --git a/arch/arm/dts/stm32mp157c-odyssey-som-u-boot.dtsi b/arch/arm/dts/stm32mp157c-odyssey-som-u-boot.dtsi
index 6be7288..4ff8483 100644
--- a/arch/arm/dts/stm32mp157c-odyssey-som-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-odyssey-som-u-boot.dtsi
@@ -123,3 +123,24 @@
 		u-boot,dm-pre-reloc;
 	};
 };
+
+&sdmmc2 {
+	u-boot,dm-spl;
+};
+
+&sdmmc2_b4_pins_a {
+	u-boot,dm-spl;
+	pins1 {
+		u-boot,dm-spl;
+	};
+	pins2 {
+		u-boot,dm-spl;
+	};
+};
+
+&sdmmc2_d47_pins_d {
+	u-boot,dm-spl;
+	pins {
+		u-boot,dm-spl;
+	};
+};
diff --git a/arch/arm/dts/stm32mp157c-odyssey-som.dtsi b/arch/arm/dts/stm32mp157c-odyssey-som.dtsi
index e367a31..1510a5b 100644
--- a/arch/arm/dts/stm32mp157c-odyssey-som.dtsi
+++ b/arch/arm/dts/stm32mp157c-odyssey-som.dtsi
@@ -264,14 +264,17 @@
 
 &sdmmc2 {
 	pinctrl-names = "default", "opendrain", "sleep";
-	pinctrl-0 = <&sdmmc2_b4_pins_a>;
-	pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
-	pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>;
-	broken-cd;
-	disable-wp;
+	pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_d>;
+	pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_d>;
+	pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_d>;
+	non-removable;
+	no-sd;
+	no-sdio;
 	st,neg-edge;
-	bus-width = <4>;
+	bus-width = <8>;
 	vmmc-supply = <&v3v3>;
+	vqmmc-supply = <&vdd>;
+	mmc-ddr-3_3v;
 	status = "okay";
 };
 
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
index e36501a..feff73c 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
@@ -45,7 +45,6 @@
 	bool reset = false;
 	struct image_header_s header;
 	struct stm32prog_data *data;
-	u32 uimage, dtb;
 
 	if (argc < 3 ||  argc > 5)
 		return CMD_RET_USAGE;
@@ -78,10 +77,12 @@
 		if (header.type == HEADER_STM32IMAGE) {
 			size = header.image_length + BL_HEADER_SIZE;
 
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
 			/* uImage detected in STM32IMAGE, execute the script */
 			if (IMAGE_FORMAT_LEGACY ==
 			    genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
 				return image_source_script(addr + BL_HEADER_SIZE, "script@1");
+#endif
 		}
 	}
 
@@ -98,7 +99,7 @@
 
 	ret = stm32prog_init(data, addr, size);
 	if (ret)
-		printf("Invalid or missing layout file.");
+		log_debug("Invalid or missing layout file at 0x%lx.\n", addr);
 
 	/* prepare DFU for device read/write */
 	ret = stm32prog_dfu_init(data);
@@ -119,21 +120,23 @@
 		goto cleanup;
 	}
 
-	uimage = data->uimage;
-	dtb = data->dtb;
-
 	stm32prog_clean(data);
 	free(stm32prog_data);
 	stm32prog_data = NULL;
 
 	puts("Download done\n");
 
-	if (uimage) {
+	if (data->uimage) {
 		char boot_addr_start[20];
 		char dtb_addr[20];
+		char initrd_addr[40];
 		char *bootm_argv[5] = {
 			"bootm", boot_addr_start, "-", dtb_addr, NULL
 		};
+		u32 uimage = data->uimage;
+		u32 dtb = data->dtb;
+		u32 initrd = data->initrd;
+
 		if (!dtb)
 			bootm_argv[3] = env_get("fdtcontroladdr");
 		else
@@ -142,8 +145,15 @@
 
 		snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
 			 "0x%x", uimage);
-		printf("Booting kernel at %s - %s...\n\n\n",
-		       boot_addr_start, bootm_argv[3]);
+
+		if (initrd) {
+			snprintf(initrd_addr, sizeof(initrd_addr) - 1, "0x%x:0x%x",
+				 initrd, data->initrd_size);
+			bootm_argv[2] = initrd_addr;
+		}
+
+		printf("Booting kernel at %s %s %s...\n\n\n",
+		       boot_addr_start, bootm_argv[2], bootm_argv[3]);
 		/* Try bootm for legacy and FIT format image */
 		if (genimg_get_format((void *)uimage) != IMAGE_FORMAT_INVALID)
 			do_bootm(cmdtp, 0, 4, bootm_argv);
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
index 4c4d8a7..f7c93a1 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
@@ -369,23 +369,24 @@
 	bool end_of_line, eof;
 	char *p, *start, *last, *col;
 	struct stm32prog_part_t *part;
+	struct image_header_s header;
 	int part_list_size;
 	int i;
 
 	data->part_nb = 0;
 
 	/* check if STM32image is detected */
-	stm32prog_header_check((struct raw_header_s *)addr, &data->header);
-	if (data->header.type == HEADER_STM32IMAGE) {
+	stm32prog_header_check((struct raw_header_s *)addr, &header);
+	if (header.type == HEADER_STM32IMAGE) {
 		u32 checksum;
 
 		addr = addr + BL_HEADER_SIZE;
-		size = data->header.image_length;
+		size = header.image_length;
 
-		checksum = stm32prog_header_checksum(addr, &data->header);
-		if (checksum != data->header.image_checksum) {
+		checksum = stm32prog_header_checksum(addr, &header);
+		if (checksum != header.image_checksum) {
 			stm32prog_err("Layout: invalid checksum : 0x%x expected 0x%x",
-				      checksum, data->header.image_checksum);
+				      checksum, header.image_checksum);
 			return -EIO;
 		}
 	}
@@ -1149,7 +1150,10 @@
 	struct dfu_entity *dfu;
 	int alt_nb;
 
-	alt_nb = 3; /* number of virtual = CMD, OTP, PMIC*/
+	alt_nb = 2; /* number of virtual = CMD, OTP*/
+	if (CONFIG_IS_ENABLED(DM_PMIC))
+		alt_nb++; /* PMIC NVMEM*/
+
 	if (data->part_nb == 0)
 		alt_nb++;  /* +1 for FlashLayout */
 	else
@@ -1472,7 +1476,7 @@
 	return ret;
 }
 
-static void stm32prog_end_phase(struct stm32prog_data *data)
+static void stm32prog_end_phase(struct stm32prog_data *data, u64 offset)
 {
 	if (data->phase == PHASE_FLASHLAYOUT) {
 		if (parse_flash_layout(data, STM32_DDR_BASE, 0))
@@ -1488,6 +1492,10 @@
 			data->uimage = data->cur_part->addr;
 		if (data->cur_part->part_type == PART_FILESYSTEM)
 			data->dtb = data->cur_part->addr;
+		if (data->cur_part->part_type == PART_BINARY) {
+			data->initrd = data->cur_part->addr;
+			data->initrd_size = offset;
+		}
 	}
 
 	if (CONFIG_IS_ENABLED(MMC) &&
@@ -1727,7 +1735,6 @@
 	free(data->part_array);
 	free(data->otp_part);
 	free(data->buffer);
-	free(data->header_data);
 }
 
 /* DFU callback: used after serial and direct DFU USB access */
@@ -1747,7 +1754,7 @@
 	if (dfu->dev_type == DFU_DEV_RAM) {
 		if (dfu->alt == 0 &&
 		    stm32prog_data->phase == PHASE_FLASHLAYOUT) {
-			stm32prog_end_phase(stm32prog_data);
+			stm32prog_end_phase(stm32prog_data, dfu->offset);
 			/* waiting DFU DETACH for reenumeration */
 		}
 	}
@@ -1756,7 +1763,7 @@
 		return;
 
 	if (dfu->alt == stm32prog_data->cur_part->alt_id) {
-		stm32prog_end_phase(stm32prog_data);
+		stm32prog_end_phase(stm32prog_data, dfu->offset);
 		stm32prog_next_phase(stm32prog_data);
 	}
 }
@@ -1776,3 +1783,17 @@
 		log_debug("dfu offset = 0x%llx\n", dfu->offset);
 	}
 }
+
+void dfu_error_callback(struct dfu_entity *dfu, const char *msg)
+{
+	struct stm32prog_data *data = stm32prog_data;
+
+	if (!stm32prog_data)
+		return;
+
+	if (!stm32prog_data->cur_part)
+		return;
+
+	if (dfu->alt == stm32prog_data->cur_part->alt_id)
+		stm32prog_err(msg);
+}
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
index 581b10d..efb51a3 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
@@ -132,14 +132,9 @@
 	u32			*otp_part;
 	u8			pmic_part[PMIC_SIZE];
 
-	/* STM32 header information */
-	struct raw_header_s	*header_data;
-	struct image_header_s	header;
-
 	/* SERIAL information */
 	u32	cursor;
 	u32	packet_number;
-	u32	checksum;
 	u8	*buffer; /* size = USART_RAM_BUFFER_SIZE*/
 	int	dfu_seq;
 	u8	read_phase;
@@ -147,6 +142,8 @@
 	/* bootm information */
 	u32	uimage;
 	u32	dtb;
+	u32	initrd;
+	u32	initrd_size;
 };
 
 extern struct stm32prog_data *stm32prog_data;
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c
index 2b92e3b..7de6266 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c
@@ -10,6 +10,7 @@
 #include <malloc.h>
 #include <serial.h>
 #include <watchdog.h>
+#include <asm/arch/sys_proto.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
 #include <linux/delay.h>
@@ -19,8 +20,7 @@
 /* - configuration part -----------------------------*/
 #define USART_BL_VERSION	0x40	/* USART bootloader version V4.0*/
 #define UBOOT_BL_VERSION	0x03	/* bootloader version V0.3*/
-#define DEVICE_ID_BYTE1		0x05	/* MSB byte of device ID*/
-#define DEVICE_ID_BYTE2		0x00	/* LSB byte of device ID*/
+
 #define USART_RAM_BUFFER_SIZE	256	/* Size of USART_RAM_Buf buffer*/
 
 /* - Commands -----------------------------*/
@@ -60,6 +60,9 @@
 
 #define NB_CMD sizeof(cmd_id)
 
+/* with 115200 bauds, 20 ms allow to receive the 256 bytes buffer */
+#define TIMEOUT_SERIAL_BUFFER	30
+
 /* DFU support for serial *********************************************/
 static struct dfu_entity *stm32prog_get_entity(struct stm32prog_data *data)
 {
@@ -264,6 +267,7 @@
 {
 	struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
 	int err;
+	ulong start = get_timer(0);
 
 	do {
 		err = ops->getc(down_serial_dev);
@@ -273,6 +277,10 @@
 		} else if (err == -EAGAIN) {
 			ctrlc();
 			WATCHDOG_RESET();
+			if (get_timer(start) > TIMEOUT_SERIAL_BUFFER) {
+				err = -ETIMEDOUT;
+				break;
+			}
 		} else {
 			break;
 		}
@@ -292,56 +300,6 @@
 }
 
 /* Helper function ************************************************/
-
-static u8 stm32prog_header(struct stm32prog_data *data)
-{
-	u8 ret;
-	u8 boot = 0;
-	struct dfu_entity *dfu_entity;
-	u64 size = 0;
-
-	dfu_entity = stm32prog_get_entity(data);
-	if (!dfu_entity)
-		return -ENODEV;
-
-	printf("\nSTM32 download write %s\n", dfu_entity->name);
-
-	/* force cleanup to avoid issue with previous read */
-	dfu_transaction_cleanup(dfu_entity);
-
-	stm32prog_header_check(data->header_data, &data->header);
-
-	/* no stm32 image header : max size is partition size */
-	if (data->header.type != HEADER_STM32IMAGE) {
-		dfu_entity->get_medium_size(dfu_entity, &size);
-		data->header.image_length = size;
-	}
-
-	/**** Flash the header if necessary for boot partition */
-	if (data->phase < PHASE_FIRST_USER)
-		boot = 1;
-
-	/* write header if boot partition */
-	if (boot) {
-		if (ret) {
-			stm32prog_err("invalid header (error %d)", ret);
-		} else {
-			ret = stm32prog_write(data,
-					      (u8 *)data->header_data,
-					      BL_HEADER_SIZE);
-		}
-	} else {
-		if (ret)
-			printf("  partition without checksum\n");
-		ret = 0;
-	}
-
-	free(data->header_data);
-	data->header_data = NULL;
-
-	return ret;
-}
-
 static u8 stm32prog_start(struct stm32prog_data *data, u32 address)
 {
 	u8 ret = 0;
@@ -388,23 +346,6 @@
 		data->dfu_seq = 0;
 
 		printf("\n  received length = 0x%x\n", data->cursor);
-		if (data->header.type == HEADER_STM32IMAGE) {
-			if (data->cursor !=
-			    (data->header.image_length + BL_HEADER_SIZE)) {
-				stm32prog_err("transmission interrupted (length=0x%x expected=0x%x)",
-					      data->cursor,
-					      data->header.image_length +
-					      BL_HEADER_SIZE);
-				return -EIO;
-			}
-			if (data->header.image_checksum != data->checksum) {
-				stm32prog_err("invalid checksum received (0x%x expected 0x%x)",
-					      data->checksum,
-					      data->header.image_checksum);
-				return -EIO;
-			}
-			printf("\n  checksum OK (0x%x)\n", data->checksum);
-		}
 
 		/* update DFU with received flashlayout */
 		if (data->phase == PHASE_FLASHLAYOUT)
@@ -495,10 +436,12 @@
  */
 static void get_id_command(struct stm32prog_data *data)
 {
+	u32 cpu = get_cpu_dev();
+
 	/* Send Device IDCode */
 	stm32prog_serial_putc(0x1);
-	stm32prog_serial_putc(DEVICE_ID_BYTE1);
-	stm32prog_serial_putc(DEVICE_ID_BYTE2);
+	stm32prog_serial_putc((cpu >> 8) & 0xFF);
+	stm32prog_serial_putc(cpu & 0xFF);
 	stm32prog_serial_result(ACK_BYTE);
 }
 
@@ -627,14 +570,12 @@
 	u32 counter = 0x0, codesize = 0x0;
 	u8 *ramaddress = 0;
 	u8 rcv_data = 0x0;
-	struct image_header_s *image_header = &data->header;
 	u32 cursor = data->cursor;
 	long size = 0;
 	u8 operation;
 	u32 packet_number;
 	u32 result = ACK_BYTE;
 	u8 ret;
-	unsigned int i;
 	bool error;
 	int rcv;
 
@@ -668,13 +609,8 @@
 	if (packet_number == 0) {
 		/* erase: re-initialize the image_header struct */
 		data->packet_number = 0;
-		if (data->header_data)
-			memset(data->header_data, 0, BL_HEADER_SIZE);
-		else
-			data->header_data = calloc(1, BL_HEADER_SIZE);
 		cursor = 0;
 		data->cursor = 0;
-		data->checksum = 0;
 		/*idx = cursor;*/
 	} else {
 		data->packet_number++;
@@ -722,7 +658,7 @@
 		printf("transmission error on packet %d, byte %d\n",
 		       packet_number, codesize - counter);
 		/* waiting end of packet before flush & NACK */
-		mdelay(30);
+		mdelay(TIMEOUT_SERIAL_BUFFER);
 		data->packet_number--;
 		result = NACK_BYTE;
 		goto end;
@@ -740,80 +676,33 @@
 		/* wait to be sure that all data are received
 		 * in the FIFO before flush
 		 */
-		mdelay(30);
+		mdelay(TIMEOUT_SERIAL_BUFFER);
 		data->packet_number--;
 		result = NACK_BYTE;
 		goto end;
 	}
 
-	/* Update current position in buffer */
-	data->cursor += codesize;
+	switch (operation) {
+	case PHASE_OTP:
+		size = codesize;
+		ret = stm32prog_otp_write(data, cursor, data->buffer, &size);
+		break;
 
-	if (operation == PHASE_OTP) {
-		size = data->cursor - cursor;
-		/* no header for OTP */
-		if (stm32prog_otp_write(data, cursor,
-					data->buffer, &size))
-			result = ABORT_BYTE;
-		goto end;
+	case PHASE_PMIC:
+		size = codesize;
+		ret = stm32prog_pmic_write(data, cursor, data->buffer, &size);
+		break;
+
+	default:
+		ret = stm32prog_write(data, data->buffer, codesize);
+		break;
 	}
 
-	if (operation == PHASE_PMIC) {
-		size = data->cursor - cursor;
-		/* no header for PMIC */
-		if (stm32prog_pmic_write(data, cursor,
-					 data->buffer, &size))
-			result = ABORT_BYTE;
-		goto end;
-	}
-
-	if (cursor < BL_HEADER_SIZE) {
-		/* size = portion of header in this chunck */
-		if (data->cursor >= BL_HEADER_SIZE)
-			size = BL_HEADER_SIZE - cursor;
-		else
-			size = data->cursor - cursor;
-		memcpy((void *)((u32)(data->header_data) + cursor),
-		       data->buffer, size);
-		cursor += size;
-
-		if (cursor == BL_HEADER_SIZE) {
-			/* Check and Write the header */
-			if (stm32prog_header(data)) {
-				result = ABORT_BYTE;
-				goto end;
-			}
-		} else {
-			goto end;
-		}
-	}
-
-	if (data->header.type == HEADER_STM32IMAGE) {
-		if (data->cursor <= BL_HEADER_SIZE)
-			goto end;
-		/* compute checksum on payload */
-		for (i = (unsigned long)size; i < codesize; i++)
-			data->checksum += data->buffer[i];
-
-		if (data->cursor >
-		    image_header->image_length + BL_HEADER_SIZE) {
-			log_err("expected size exceeded\n");
-			result = ABORT_BYTE;
-			goto end;
-		}
-
-		/* write data (payload) */
-		ret = stm32prog_write(data,
-				      &data->buffer[size],
-				      codesize - size);
-	} else {
-		/* write all */
-		ret = stm32prog_write(data,
-				      data->buffer,
-				      codesize);
-	}
 	if (ret)
 		result = ABORT_BYTE;
+	else
+		/* Update current position in buffer */
+		data->cursor += codesize;
 
 end:
 	stm32prog_serial_result(result);
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
index bc44d9f..d4a3f7e 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
@@ -207,13 +207,10 @@
 
 	if (stm32prog_data->phase == PHASE_FLASHLAYOUT) {
 		ret = run_usb_dnl_gadget(dev, "usb_dnl_dfu");
-		if (ret || stm32prog_data->phase == PHASE_DO_RESET)
+		if (ret || stm32prog_data->phase != PHASE_FLASHLAYOUT)
 			return ret;
 		/* prepare the second enumeration with the FlashLayout */
-		if (stm32prog_data->phase == PHASE_FLASHLAYOUT)
-			stm32prog_dfu_init(data);
-		/* found next selected partition */
-		stm32prog_next_phase(data);
+		stm32prog_dfu_init(data);
 	}
 
 	ret = run_usb_dnl_gadget(dev, "usb_dnl_dfu");
diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c
index ac1af71..d7c1857 100644
--- a/board/dhelectronics/dh_stm32mp1/board.c
+++ b/board/dhelectronics/dh_stm32mp1/board.c
@@ -660,11 +660,11 @@
 	bool eth_ref_clk_sel_reg = false;
 
 	/* Gigabit Ethernet 125MHz clock selection. */
-	eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
+	eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel");
 
 	/* Ethernet 50Mhz RMII clock selection */
 	eth_ref_clk_sel_reg =
-		dev_read_bool(dev, "st,eth_ref_clk_sel");
+		dev_read_bool(dev, "st,eth-ref-clk-sel");
 
 	syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
 
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 261ec15..18b8870 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -733,11 +733,11 @@
 	bool eth_ref_clk_sel_reg = false;
 
 	/* Gigabit Ethernet 125MHz clock selection. */
-	eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
+	eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel");
 
 	/* Ethernet 50Mhz RMII clock selection */
 	eth_ref_clk_sel_reg =
-		dev_read_bool(dev, "st,eth_ref_clk_sel");
+		dev_read_bool(dev, "st,eth-ref-clk-sel");
 
 	syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
 
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index cac0f6a..1425421 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -160,7 +160,7 @@
 int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
 {
 	int i, ret, err, count;
-	
+
 	bulk->count = 0;
 
 	count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0);
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 213a20e..ff1859d 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -45,6 +45,14 @@
 }
 
 /*
+ * The purpose of the dfu_error_callback() function is to
+ * provide callback for dfu user
+ */
+__weak void dfu_error_callback(struct dfu_entity *dfu, const char *msg)
+{
+}
+
+/*
  * The purpose of the dfu_usb_get_reset() function is to
  * provide information if after USB_DETACH request
  * being sent the dfu-util performed reset of USB
@@ -342,6 +350,7 @@
 		printf("%s: Wrong sequence number! [%d] [%d]\n",
 		       __func__, dfu->i_blk_seq_num, blk_seq_num);
 		dfu_transaction_cleanup(dfu);
+		dfu_error_callback(dfu, "Wrong sequence number");
 		return -1;
 	}
 
@@ -366,6 +375,7 @@
 		ret = dfu_write_buffer_drain(dfu);
 		if (ret) {
 			dfu_transaction_cleanup(dfu);
+			dfu_error_callback(dfu, "DFU write error");
 			return ret;
 		}
 	}
@@ -375,6 +385,7 @@
 		pr_err("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
 		      size, dfu->i_buf_end);
 		dfu_transaction_cleanup(dfu);
+		dfu_error_callback(dfu, "Buffer overflow");
 		return -1;
 	}
 
@@ -386,6 +397,7 @@
 		ret = dfu_write_buffer_drain(dfu);
 		if (ret) {
 			dfu_transaction_cleanup(dfu);
+			dfu_error_callback(dfu, "DFU write error");
 			return ret;
 		}
 	}
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c
index ec40b8f..894b570 100644
--- a/drivers/dfu/dfu_mtd.c
+++ b/drivers/dfu/dfu_mtd.c
@@ -254,7 +254,6 @@
 {
 	char *st;
 	struct mtd_info *mtd;
-	bool has_pages;
 	int ret, part;
 
 	mtd = get_mtd_device_nm(devstr);
@@ -264,9 +263,7 @@
 
 	dfu->dev_type = DFU_DEV_MTD;
 	dfu->data.mtd.info = mtd;
-
-	has_pages = mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
-	dfu->max_buf_size = has_pages ? mtd->erasesize : 0;
+	dfu->max_buf_size = mtd->erasesize;
 
 	st = strsep(&s, " ");
 	if (!strcmp(st, "raw")) {
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index 4acc904..8f4aabc 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -148,23 +148,24 @@
 				const struct spi_mem_op *op)
 {
 	u32 sr;
-	int ret;
+	int ret = 0;
 
-	if (!op->data.nbytes)
-		return _stm32_qspi_wait_for_not_busy(priv);
-
-	ret = readl_poll_timeout(&priv->regs->sr, sr,
-				 sr & STM32_QSPI_SR_TCF,
-				 STM32_QSPI_CMD_TIMEOUT_US);
-	if (ret) {
-		log_err("cmd timeout (stat:%#x)\n", sr);
-	} else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
-		log_err("transfer error (stat:%#x)\n", sr);
-		ret = -EIO;
+	if (op->data.nbytes) {
+		ret = readl_poll_timeout(&priv->regs->sr, sr,
+					 sr & STM32_QSPI_SR_TCF,
+					 STM32_QSPI_CMD_TIMEOUT_US);
+		if (ret) {
+			log_err("cmd timeout (stat:%#x)\n", sr);
+		} else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
+			log_err("transfer error (stat:%#x)\n", sr);
+			ret = -EIO;
+		}
+		/* clear flags */
+		writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
 	}
 
-	/* clear flags */
-	writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
+	if (!ret)
+		ret = _stm32_qspi_wait_for_not_busy(priv);
 
 	return ret;
 }
diff --git a/include/dfu.h b/include/dfu.h
index afada39..f686898 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -377,6 +377,17 @@
  */
 void dfu_flush_callback(struct dfu_entity *dfu);
 
+/**
+ * dfu_error_callback() - weak callback called at the DFU write error
+ *
+ * It is a callback function called by DFU stack after DFU write error.
+ * This function allows to manage some board specific behavior on DFU targets
+ *
+ * @dfu:	pointer to the dfu_entity which cause the error
+ * @msg:	the message of the error
+ */
+void dfu_error_callback(struct dfu_entity *dfu, const char *msg);
+
 int dfu_transaction_initiate(struct dfu_entity *dfu, bool read);
 void dfu_transaction_cleanup(struct dfu_entity *dfu);