diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c index 33009bc637..7adb304a23 100644 --- a/payloads/libpayload/drivers/usb/xhci.c +++ b/payloads/libpayload/drivers/usb/xhci.c @@ -551,6 +551,14 @@ xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps, } else { TRB_SET(TT, trb, TRB_NORMAL); } + /* + * This is a workaround for Synopsys DWC3. If the ENT flag is + * not set for the Normal and Data Stage TRBs. We get Event TRB + * with length 0x20d from the controller when we enqueue a TRB + * for the IN endpoint with length 0x200. + */ + if (!length) + TRB_SET(ENT, trb, 1); xhci_enqueue_trb(tr); diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h index 43800d8d49..3861858b44 100644 --- a/payloads/libpayload/drivers/usb/xhci_private.h +++ b/payloads/libpayload/drivers/usb/xhci_private.h @@ -93,6 +93,9 @@ enum { TRB_DIR_OUT = 0, TRB_DIR_IN = 1 }; #define TRB_TC_FIELD control /* TC - Toggle Cycle */ #define TRB_TC_START 1 #define TRB_TC_LEN 1 +#define TRB_ENT_FIELD control /* ENT - Evaluate Next TRB */ +#define TRB_ENT_START 1 +#define TRB_ENT_LEN 1 #define TRB_ISP_FIELD control /* ISP - Interrupt-on Short Packet */ #define TRB_ISP_START 2 #define TRB_ISP_LEN 1