summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--payloads/libpayload/drivers/usb/dwc2.c23
-rw-r--r--payloads/libpayload/drivers/usb/dwc2_private.h16
2 files changed, 33 insertions, 6 deletions
diff --git a/payloads/libpayload/drivers/usb/dwc2.c b/payloads/libpayload/drivers/usb/dwc2.c
index 1092cb4ee3..71c4967e7e 100644
--- a/payloads/libpayload/drivers/usb/dwc2.c
+++ b/payloads/libpayload/drivers/usb/dwc2.c
@@ -35,11 +35,12 @@ static void dwc2_reinit(hci_t *controller)
gintsts_t gintsts = { .d32 = 0 };
gahbcfg_t gahbcfg = { .d32 = 0 };
grxfsiz_t grxfsiz = { .d32 = 0 };
+ ghwcfg3_t hwcfg3 = { .d32 = 0 };
hcintmsk_t hcintmsk = { .d32 = 0 };
gnptxfsiz_t gnptxfsiz = { .d32 = 0 };
const int timeout = 10000;
- int i;
+ int i, fifo_blocks, tx_blocks;
/* Wait for AHB idle */
for (i = 0; i < timeout; i++) {
@@ -86,10 +87,24 @@ static void dwc2_reinit(hci_t *controller)
* The non-periodic tx fifo and rx fifo share one continuous
* piece of IP-internal SRAM.
*/
- grxfsiz.rxfdep = DWC2_RXFIFO_DEPTH;
+
+ /*
+ * Read total data FIFO depth from HWCFG3
+ * this value is in terms of 32-bit words
+ */
+ hwcfg3.d32 = readl(&reg->core.ghwcfg3);
+ /*
+ * Reserve 2 spaces for the status entries of received packets
+ * and 2 spaces for bulk and control OUT endpoints. Calculate how
+ * many blocks can be alloted, assume largest packet size is 512.
+ */
+ fifo_blocks = (hwcfg3.dfifodepth - 4) / (512 / 4);
+ tx_blocks = fifo_blocks / 2;
+
+ grxfsiz.rxfdep = (fifo_blocks - tx_blocks) * (512 / 4) + 4;
writel(grxfsiz.d32, &reg->core.grxfsiz);
- gnptxfsiz.nptxfstaddr = DWC2_RXFIFO_DEPTH;
- gnptxfsiz.nptxfdep = DWC2_NPTXFIFO_DEPTH;
+ gnptxfsiz.nptxfstaddr = grxfsiz.rxfdep;
+ gnptxfsiz.nptxfdep = tx_blocks * (512 / 4);
writel(gnptxfsiz.d32, &reg->core.gnptxfsiz);
/* Init host channels */
diff --git a/payloads/libpayload/drivers/usb/dwc2_private.h b/payloads/libpayload/drivers/usb/dwc2_private.h
index 9bd83763ea..fc658bf5fa 100644
--- a/payloads/libpayload/drivers/usb/dwc2_private.h
+++ b/payloads/libpayload/drivers/usb/dwc2_private.h
@@ -374,7 +374,6 @@ typedef union {
struct {
unsigned nptxfstaddr:16;
unsigned nptxfdep:16;
-#define DWC2_NPTXFIFO_DEPTH 0x80
};
} gnptxfsiz_t;
@@ -390,7 +389,6 @@ typedef union {
*/
struct {
unsigned rxfdep:16;
-#define DWC2_RXFIFO_DEPTH 0x200
unsigned reserved:16;
};
} grxfsiz_t;
@@ -438,6 +436,20 @@ typedef union {
} gintsts_t;
/**
+ * This union represents the bit fields of the User HW Config3 Register
+ * (GHWCFG3).
+ */
+typedef union {
+ /* raw register data */
+ uint32_t d32;
+ /* register bits */
+ struct {
+ unsigned reserved:16;
+ unsigned dfifodepth:16;
+ };
+} ghwcfg3_t;
+
+/**
* This union represents the bit fields in the Host Configuration Register.
*/
typedef union {