summaryrefslogtreecommitdiff
path: root/src/portable/synopsys
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-25 09:27:48 +0200
committerHiFiPHile <[email protected]>2026-08-25 09:27:48 +0200
commitdfac26a272fa7bbbca2050fbe9f1ca09008e548e (patch)
treeefbc53f8f2c1e5d9c7f38e5fef6d774a20053cec /src/portable/synopsys
parente590b45fcf51f9ddace73178074e4fe6d691e319 (diff)
parent5c0e31cdabaf37f14e1f5e988a020abfc1000495 (diff)
Merge master updates into the UAC1 host branch
Bring the audio work onto the current host core and build files before applying the remaining review fixes. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'src/portable/synopsys')
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index 6c88b4f27..b2f1a93a4 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -393,10 +393,6 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
}
dep->diepdma = (uintptr_t) xfer->buffer;
dep->diepctl = depctl.value; // enable endpoint
- // Advance buffer pointer for EP0
- if (epnum == 0) {
- xfer->buffer += total_bytes;
- }
} else
#endif
{
@@ -732,6 +728,8 @@ static void handle_bus_reset(uint8_t rhport) {
tu_memclr(xfer_status, sizeof(xfer_status));
+ _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0;
+ _dcd_data.ep0_pending[TUSB_DIR_IN] = 0;
_dcd_data.sof_en = false;
_dcd_data.allocated_epin_count = 0;
@@ -1009,6 +1007,10 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
if (edpt_is_enabled(epin0)) {
edpt_disable(rhport, 0x80, false);
}
+ // a new SETUP aborts any in-progress control transfer: drop leftover EP0 chunking state so a
+ // stale latched completion cannot re-arm from it
+ _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0;
+ _dcd_data.ep0_pending[TUSB_DIR_IN] = 0;
dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, sizeof(_dcd_usbbuf.setup_buffer));
@@ -1029,24 +1031,37 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
// only handle data skip if it is setup or status related
// Normal OUT transfer complete
if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) {
+ xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) {
- // EP0 can only handle one packet Schedule another packet to be received.
+ // EP0 can only handle one packet: invalidate and advance past the received bytes, then
+ // schedule the next.
+ if (xfer->buffer != NULL) {
+ dcd_dcache_invalidate(xfer->buffer, CFG_TUD_ENDPOINT0_SIZE);
+ xfer->buffer += CFG_TUD_ENDPOINT0_SIZE;
+ }
edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT);
} else {
dwc2_dep_t* epout = &dwc2->epout[epnum];
- xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
// determine actual received bytes
const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz};
const uint16_t remain = tsiz.xfer_size;
xfer->total_len -= remain;
+ // EP0 invalidates only this (final) chunk's DMA-written bytes: DOEPDMA "is incremented on
+ // every AHB transaction" (databook 7.1.83), i.e. it points past the last word written.
+ // Read it before dma_setup_prepare() re-targets it at the setup buffer
+ uint16_t inval_len = xfer->total_len;
+ if (epnum == 0) {
+ inval_len = (uint16_t)(epout->doepdma - (uintptr_t)xfer->buffer);
+ }
+
// prepare EP0 for next setup
if(epnum == 0) {
dma_setup_prepare(rhport);
}
- dcd_dcache_invalidate(xfer->buffer, xfer->total_len);
+ dcd_dcache_invalidate(xfer->buffer, inval_len);
dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
}
@@ -1058,7 +1073,10 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin
if (diepint_bm.xfer_complete) {
if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) {
- // EP0 can only handle one packet. Schedule another packet to be transmitted.
+ // EP0 can only handle one packet: advance past the sent bytes, then schedule the next.
+ if (xfer->buffer != NULL) {
+ xfer->buffer += CFG_TUD_ENDPOINT0_SIZE;
+ }
edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN);
} else {
dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
@@ -1125,7 +1143,12 @@ static void handle_incomplete_iso_in(uint8_t rhport) {
xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
if (xfer->iso_retry > 0) {
xfer->iso_retry--;
- // Restart ISO transfe: re-write TSIZ and CTL
+ // Restart ISO transfer: re-write DMA address, TSIZ, and CTL
+ #if CFG_TUD_DWC2_DMA_ENABLE
+ if (dma_device_enabled(dwc2)) {
+ epin->diepdma = (uintptr_t) xfer->buffer;
+ }
+ #endif
dwc2_ep_tsize_t deptsiz = {.value = 0};
deptsiz.xfer_size = xfer->total_len;
deptsiz.packet_count = tu_div_ceil(xfer->total_len, xfer->max_size);