+// SPDX-License-Identifier: GPL-2.0
/**
* gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link
*
* to uboot.
*
* commit 8e74475b0e : usb: dwc3: gadget: use udc-core's reset notifier
- *
- * SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <malloc.h>
#include <asm/dma-mapping.h>
#include <usb/lin_gadget_compat.h>
+#include <linux/bug.h>
#include <linux/list.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <asm/arch/sys_proto.h>
#include "core.h"
#include "gadget.h"
list_del(&req->list);
req->trb = NULL;
- dwc3_flush_cache((int)req->request.dma, req->request.length);
+ dwc3_flush_cache((uintptr_t)req->request.dma, req->request.length);
if (req->request.status == -EINPROGRESS)
req->request.status = status;
trb->ctrl |= DWC3_TRB_CTRL_HWO;
- dwc3_flush_cache((int)dma, length);
- dwc3_flush_cache((int)trb, sizeof(*trb));
+ dwc3_flush_cache((uintptr_t)dma, length);
+ dwc3_flush_cache((uintptr_t)trb, sizeof(*trb));
}
/*
struct dwc3_request *req, *n;
u32 trbs_left;
u32 max;
- unsigned int last_one = 0;
BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
list_for_each_entry_safe(req, n, &dep->request_list, list) {
unsigned length;
dma_addr_t dma;
- last_one = false;
dma = req->request.dma;
length = req->request.length;
- trbs_left--;
-
- if (!trbs_left)
- last_one = 1;
-
- /* Is this the last request? */
- if (list_is_last(&req->list, &dep->request_list))
- last_one = 1;
dwc3_prepare_one_trb(dep, req, dma, length,
- last_one, false, 0);
+ true, false, 0);
- if (last_one)
- break;
+ break;
}
}
req->direction = dep->direction;
req->epnum = dep->number;
+ /*
+ * DWC3 hangs on OUT requests smaller than maxpacket size,
+ * so HACK the request length
+ */
+ if (dep->direction == 0 &&
+ req->request.length < dep->endpoint.maxpacket)
+ req->request.length = dep->endpoint.maxpacket;
+
/*
* We only add to our list of requests now and
* start consuming the list once we get XferNotReady
} else {
int ret;
- usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
+ usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
struct dwc3_request *req;
struct dwc3_trb *trb;
unsigned int slot;
- int ret;
- do {
- req = next_request(&dep->req_queued);
- if (!req) {
- WARN_ON_ONCE(1);
- return 1;
- }
-
- slot = req->start_slot;
- if ((slot == DWC3_TRB_NUM - 1) &&
- usb_endpoint_xfer_isoc(dep->endpoint.desc))
- slot++;
- slot %= DWC3_TRB_NUM;
- trb = &dep->trb_pool[slot];
-
- dwc3_flush_cache((int)trb, sizeof(*trb));
- ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
- event, status);
- if (ret)
- break;
+ req = next_request(&dep->req_queued);
+ if (!req) {
+ WARN_ON_ONCE(1);
+ return 1;
+ }
- dwc3_gadget_giveback(dep, req, status);
+ slot = req->start_slot;
+ if ((slot == DWC3_TRB_NUM - 1) &&
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ slot++;
+ slot %= DWC3_TRB_NUM;
+ trb = &dep->trb_pool[slot];
- if (ret)
- break;
- } while (1);
+ dwc3_flush_cache((uintptr_t)trb, sizeof(*trb));
+ __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status);
+ dwc3_gadget_giveback(dep, req, status);
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
list_empty(&dep->req_queued)) {
static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
unsigned int evtinfo)
{
- unsigned int is_ss = evtinfo & BIT(4);
+ unsigned int is_ss = evtinfo & (1UL << 4);
/**
* WORKAROUND: DWC3 revison 2.20a with hibernation support
*/
void dwc3_gadget_uboot_handle_interrupt(struct dwc3 *dwc)
{
- dwc3_interrupt(0, dwc);
- dwc3_thread_interrupt(0, dwc);
+ int ret = dwc3_interrupt(0, dwc);
+
+ if (ret == IRQ_WAKE_THREAD) {
+ int i;
+ struct dwc3_event_buffer *evt;
+
+ dwc3_thread_interrupt(0, dwc);
+
+ /* Clean + Invalidate the buffers after touching them */
+ for (i = 0; i < dwc->num_event_buffers; i++) {
+ evt = dwc->ev_buffs[i];
+ dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
+ }
+ }
}