return controller.items[(ep_num * 2) + dir_in];
 }
 
+/**
+ * mv_flush_qh - flush cache over queue head
+ * @ep_num:    Endpoint number
+ *
+ * This function flushes cache over QH for particular endpoint.
+ */
+static void mv_flush_qh(int ep_num)
+{
+       struct ept_queue_head *head = mv_get_qh(ep_num, 0);
+       const uint32_t start = (uint32_t)head;
+       const uint32_t end = start + 2 * sizeof(*head);
+
+       flush_dcache_range(start, end);
+}
+
+/**
+ * mv_invalidate_qh - invalidate cache over queue head
+ * @ep_num:    Endpoint number
+ *
+ * This function invalidates cache over QH for particular endpoint.
+ */
+static void mv_invalidate_qh(int ep_num)
+{
+       struct ept_queue_head *head = mv_get_qh(ep_num, 0);
+       uint32_t start = (uint32_t)head;
+       uint32_t end = start + 2 * sizeof(*head);
+
+       invalidate_dcache_range(start, end);
+}
+
+/**
+ * mv_flush_qtd - flush cache over queue item
+ * @ep_num:    Endpoint number
+ *
+ * This function flushes cache over qTD pair for particular endpoint.
+ */
+static void mv_flush_qtd(int ep_num)
+{
+       struct ept_queue_item *item = mv_get_qtd(ep_num, 0);
+       const uint32_t start = (uint32_t)item;
+       const uint32_t end_raw = start + 2 * sizeof(*item);
+       const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN);
+
+       flush_dcache_range(start, end);
+}
+
+/**
+ * mv_invalidate_qtd - invalidate cache over queue item
+ * @ep_num:    Endpoint number
+ *
+ * This function invalidates cache over qTD pair for particular endpoint.
+ */
+static void mv_invalidate_qtd(int ep_num)
+{
+       struct ept_queue_item *item = mv_get_qtd(ep_num, 0);
+       const uint32_t start = (uint32_t)item;
+       const uint32_t end_raw = start + 2 * sizeof(*item);
+       const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN);
+
+       invalidate_dcache_range(start, end);
+}
+
 static struct usb_request *
 mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
 {
        else
                n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK);
 
-       if (num != 0)
+       if (num != 0) {
                head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) | CONFIG_ZLT;
+               mv_flush_qh(num);
+       }
        writel(n, &udc->epctrl[num]);
 }
 
        else
                bit = EPT_RX(num);
 
-       flush_cache(phys, len);
-       flush_cache((unsigned long)item, sizeof(struct ept_queue_item));
+       mv_flush_qh(num);
+       mv_flush_qtd(num);
+
        writel(bit, &udc->epprime);
 
        return 0;
        if (num == 0)
                ep->desc = &ep0_out_desc;
        item = mv_get_qtd(num, in);
-
+       mv_invalidate_qtd(num);
+       
        if (item->info & 0xff)
                printf("EP%d/%s FAIL nfo=%x pg0=%x\n",
                        num, in ? "in" : "out", item->info, item->page0);
        char *buf;
        head = mv_get_qh(0, 0); /* EP0 OUT */
 
-       flush_cache((unsigned long)head, sizeof(struct ept_queue_head));
+       mv_invalidate_qh(0);
        memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest));
        writel(EPT_RX(0), &udc->epstat);
        DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest),
                                & USB_DIR_IN) != 0;
                        head = mv_get_qh(num, in);
                        head->info = INFO_ACTIVE;
+                       mv_flush_qh(num);
                }
        }
 }
                        imem += sizeof(struct ept_queue_item);
 
                controller.items[i] = (struct ept_queue_item *)imem;
+
+               if (i & 1) {
+                       mv_flush_qh(i - 1);
+                       mv_flush_qtd(i - 1);
+               }
        }
 
        INIT_LIST_HEAD(&controller.gadget.ep_list);