Skip to content

Commit 07ea4aa

Browse files
tmon-nordicfabiobaltieri
authored andcommitted
drivers: udc_dwc2: Allow larger TxFIFO writes
DMA is capable of packetizing transfers on its own and the driver doesn't need to check available TxFIFO size when scheduling DMA transfer. Split packets on DWORD boundary when writing more than one packet to TxFIFO in completer mode. Signed-off-by: Tomasz Moń <[email protected]>
1 parent b7664f2 commit 07ea4aa

File tree

1 file changed

+47
-32
lines changed

1 file changed

+47
-32
lines changed

drivers/usb/udc/udc_dwc2.c

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -288,23 +288,29 @@ static int dwc2_tx_fifo_write(const struct device *dev,
288288
unsigned int key;
289289
uint32_t len;
290290

291-
spcavail = dwc2_ftx_avail(dev, ep_idx);
292-
/* Round down to multiple of endpoint MPS */
293-
spcavail -= spcavail % cfg->mps;
294-
/*
295-
* Here, the available space should be equal to the FIFO space
296-
* assigned/configured for that endpoint because we do not schedule another
297-
* transfer until the previous one has not finished. For simplicity,
298-
* we only check that the available space is not less than the endpoint
299-
* MPS.
300-
*/
301-
if (spcavail < cfg->mps) {
302-
LOG_ERR("ep 0x%02x FIFO space is too low, %u (%u)",
303-
cfg->addr, spcavail, dwc2_ftx_avail(dev, ep_idx));
304-
return -EAGAIN;
305-
}
291+
if (priv->bufferdma) {
292+
/* DMA automatically handles packet split */
293+
len = buf->len;
294+
} else {
295+
uint32_t spcavail = dwc2_ftx_avail(dev, ep_idx);
296+
297+
/* Round down to multiple of endpoint MPS */
298+
spcavail -= spcavail % cfg->mps;
299+
300+
/* Here, the available space should be equal to the FIFO space
301+
* assigned/configured for that endpoint because we do not
302+
* schedule another transfer until the previous one has not
303+
* finished. For simplicity, we only check that the available
304+
* space is not less than the endpoint MPS.
305+
*/
306+
if (spcavail < cfg->mps) {
307+
LOG_ERR("ep 0x%02x FIFO space is too low, %u (%u)",
308+
cfg->addr, spcavail, dwc2_ftx_avail(dev, ep_idx));
309+
return -EAGAIN;
310+
}
306311

307-
len = MIN(buf->len, spcavail);
312+
len = MIN(buf->len, spcavail);
313+
}
308314

309315
if (len != 0U) {
310316
max_pktcnt = dwc2_get_iept_pktctn(dev, ep_idx);
@@ -332,8 +338,8 @@ static int dwc2_tx_fifo_write(const struct device *dev,
332338
pktcnt = 1U;
333339
}
334340

335-
LOG_DBG("Prepare ep 0x%02x xfer len %u pktcnt %u spcavail %u",
336-
cfg->addr, len, pktcnt, spcavail);
341+
LOG_DBG("Prepare ep 0x%02x xfer len %u pktcnt %u",
342+
cfg->addr, len, pktcnt);
337343
priv->tx_len[ep_idx] = len;
338344

339345
/* Lock and write to endpoint FIFO */
@@ -363,22 +369,31 @@ static int dwc2_tx_fifo_write(const struct device *dev,
363369
sys_write32(USB_DWC2_DIEPINT_INEPNAKEFF, diepint_reg);
364370

365371
if (!priv->bufferdma) {
366-
/* FIFO access is always in 32-bit words */
367-
368-
for (uint32_t i = 0UL; i < len; i += d) {
369-
uint32_t val = buf->data[i];
370-
371-
if (i + 1 < len) {
372-
val |= ((uint32_t)buf->data[i + 1UL]) << 8;
373-
}
374-
if (i + 2 < len) {
375-
val |= ((uint32_t)buf->data[i + 2UL]) << 16;
376-
}
377-
if (i + 3 < len) {
378-
val |= ((uint32_t)buf->data[i + 3UL]) << 24;
372+
const uint8_t *src = buf->data;
373+
uint32_t pktlen;
374+
375+
while (pktcnt > 0) {
376+
uint32_t pktlen = MIN(len, cfg->mps);
377+
378+
for (uint32_t i = 0UL; i < pktlen; i += d) {
379+
uint32_t val = src[i];
380+
381+
if (i + 1 < pktlen) {
382+
val |= ((uint32_t)src[i + 1UL]) << 8;
383+
}
384+
if (i + 2 < pktlen) {
385+
val |= ((uint32_t)src[i + 2UL]) << 16;
386+
}
387+
if (i + 3 < pktlen) {
388+
val |= ((uint32_t)src[i + 3UL]) << 24;
389+
}
390+
391+
sys_write32(val, UDC_DWC2_EP_FIFO(base, ep_idx));
379392
}
380393

381-
sys_write32(val, UDC_DWC2_EP_FIFO(base, ep_idx));
394+
pktcnt--;
395+
src += pktlen;
396+
len -= pktlen;
382397
}
383398
}
384399

0 commit comments

Comments
 (0)