diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 1eb92e54176148081491ff449ba1107f90eaf641..07011e99a850fafa7475d02451c8f358986b7f3c 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -74,6 +74,11 @@ unsigned char *dfu_free_buf(void)
 	return dfu_buf;
 }
 
+unsigned long dfu_get_buf_size(void)
+{
+	return dfu_buf_size;
+}
+
 unsigned char *dfu_get_buf(void)
 {
 	char *s;
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 37d04a19285e605a6d4e34ae9b54b989eca28891..a045864d730686448c4740eccd56585a80291f54 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -40,6 +40,7 @@ struct f_dfu {
 
 	/* Send/received block number is handy for data integrity check */
 	int                             blk_seq_num;
+	unsigned int                    poll_timeout;
 };
 
 typedef int (*dfu_state_fn) (struct f_dfu *,
@@ -128,6 +129,33 @@ static struct usb_gadget_strings *dfu_strings[] = {
 	NULL,
 };
 
+static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms)
+{
+	/*
+	 * The bwPollTimeout DFU_GETSTATUS request payload provides information
+	 * about minimum time, in milliseconds, that the host should wait before
+	 * sending a subsequent DFU_GETSTATUS request
+	 *
+	 * This permits the device to vary the delay depending on its need to
+	 * erase or program the memory
+	 *
+	 */
+
+	unsigned char *p = (unsigned char *)&ms;
+
+	if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) {
+		dstat->bwPollTimeout[0] = 0;
+		dstat->bwPollTimeout[1] = 0;
+		dstat->bwPollTimeout[2] = 0;
+
+		return;
+	}
+
+	dstat->bwPollTimeout[0] = *p++;
+	dstat->bwPollTimeout[1] = *p++;
+	dstat->bwPollTimeout[2] = *p;
+}
+
 /*-------------------------------------------------------------------------*/
 
 static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
@@ -157,11 +185,15 @@ static void handle_getstatus(struct usb_request *req)
 		break;
 	}
 
+	dfu_set_poll_timeout(dstat, 0);
+
+	if (f_dfu->poll_timeout)
+		if (!(f_dfu->blk_seq_num %
+		      (dfu_get_buf_size() / DFU_USB_BUFSIZ)))
+			dfu_set_poll_timeout(dstat, f_dfu->poll_timeout);
+
 	/* send status response */
 	dstat->bStatus = f_dfu->dfu_status;
-	dstat->bwPollTimeout[0] = 0;
-	dstat->bwPollTimeout[1] = 0;
-	dstat->bwPollTimeout[2] = 0;
 	dstat->bState = f_dfu->dfu_state;
 	dstat->iString = 0;
 }
@@ -723,8 +755,9 @@ static int dfu_bind_config(struct usb_configuration *c)
 	f_dfu->usb_function.unbind = dfu_unbind;
 	f_dfu->usb_function.set_alt = dfu_set_alt;
 	f_dfu->usb_function.disable = dfu_disable;
-	f_dfu->usb_function.strings = dfu_generic_strings,
-	f_dfu->usb_function.setup = dfu_handle,
+	f_dfu->usb_function.strings = dfu_generic_strings;
+	f_dfu->usb_function.setup = dfu_handle;
+	f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT;
 
 	status = usb_add_function(c, &f_dfu->usb_function);
 	if (status)
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
index cc2c45567b6cb2e0830d1275b144a75186bd2dfa..0c29954add7d8c32f8cf4aea2ca0415c1e024b64 100644
--- a/drivers/usb/gadget/f_dfu.h
+++ b/drivers/usb/gadget/f_dfu.h
@@ -82,4 +82,6 @@ struct dfu_function_descriptor {
 	__le16				wTransferSize;
 	__le16				bcdDFUVersion;
 } __packed;
+
+#define DFU_POLL_TIMEOUT_MASK           (0xFFFFFFUL)
 #endif /* __F_DFU_H_ */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 8bd1eb8a99836f16f95113ac6d2e68b339cf5489..17187caed4827841615bf2f3a66b915bb291a131 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -201,6 +201,9 @@ static int ehci_shutdown(struct ehci_ctrl *ctrl)
 	int i, ret = 0;
 	uint32_t cmd, reg;
 
+	if (!ctrl || !ctrl->hcor)
+		return -EINVAL;
+
 	cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
 	cmd &= ~(CMD_PSE | CMD_ASE);
 	ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
@@ -945,7 +948,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 #endif
 	/* Set the high address word (aka segment) for 64-bit controller */
 	if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1)
-		ehci_writel(ehcic[index].hcor->or_ctrldssegment, 0);
+		ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0);
 
 	qh_list = &ehcic[index].qh_list;
 
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 7a1ffe5e28bbc1fd6bf9dc806649e49a30d1ec2c..991b19998b7e407a214f698939284577d61cb4da 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -54,9 +54,31 @@ static pci_dev_t ehci_find_class(int index)
 					bdf += PCI_BDF(0, 0, 1)) {
 				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
 						      &class);
-				if ((class >> 8 == PCI_CLASS_SERIAL_USB_EHCI)
-						&& !index--)
-					return bdf;
+				class >>= 8;
+				/*
+				 * Here be dragons! In case we have multiple
+				 * PCI EHCI controllers, this function will
+				 * be called multiple times as well. This
+				 * function will scan the PCI busses, always
+				 * starting from bus 0, device 0, function 0,
+				 * until it finds an USB controller. The USB
+				 * stack gives us an 'index' of a controller
+				 * that is currently being registered, which
+				 * is a number, starting from 0 and growing
+				 * in ascending order as controllers are added.
+				 * To avoid probing the same controller in tne
+				 * subsequent runs of this function, we will
+				 * skip 'index - 1' detected controllers and
+				 * report the index'th controller.
+				 */
+				if (class != PCI_CLASS_SERIAL_USB_EHCI)
+					continue;
+				if (index) {
+					index--;
+					continue;
+				}
+				/* Return index'th controller. */
+				return bdf;
 			}
 		}
 	}
diff --git a/include/configs/trats.h b/include/configs/trats.h
index 08771422ec42598c168641165488f5891c6749b1..6cd15c25bdbdfc5ce29160b376b2443e684629c9 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -99,6 +99,7 @@
 #define CONFIG_THOR_FUNCTION
 
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_32M
+#define DFU_DEFAULT_POLL_TIMEOUT 300
 #define CONFIG_DFU_FUNCTION
 #define CONFIG_DFU_MMC
 
diff --git a/include/dfu.h b/include/dfu.h
index cc140449271d7f8db2b72c93a5d9d614ca74f939..f973426aa90b321e34e0127e785f114b869261f4 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -77,6 +77,9 @@ static inline unsigned int get_mmc_blk_size(int dev)
 #ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
 #define CONFIG_SYS_DFU_MAX_FILE_SIZE CONFIG_SYS_DFU_DATA_BUF_SIZE
 #endif
+#ifndef DFU_DEFAULT_POLL_TIMEOUT
+#define DFU_DEFAULT_POLL_TIMEOUT 0
+#endif
 
 struct dfu_entity {
 	char			name[DFU_NAME_SIZE];
@@ -131,6 +134,7 @@ bool dfu_reset(void);
 int dfu_init_env_entities(char *interface, int dev);
 unsigned char *dfu_get_buf(void);
 unsigned char *dfu_free_buf(void);
+unsigned long dfu_get_buf_size(void);
 
 int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
 int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);