DESC_OP_EN is the DMA mode. It does not tell the direction. The write handler used it as the direction anyway: set meant IN, clear meant OUT.
Both directions support both modes. So take the direction from EP_CONFIG.DIR_OUT first, then take the mode from DESC_OP_EN. The model does not support OUT descriptor mode. Log it as not implemented. It does not support IN single stage mode yet either, so that path does nothing until the next patch. Signed-off-by: Jamin Lin <[email protected]> --- hw/usb/aspeed-udc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/usb/aspeed-udc.c b/hw/usb/aspeed-udc.c index 4572914e16..c48e2c5f1b 100644 --- a/hw/usb/aspeed-udc.c +++ b/hw/usb/aspeed-udc.c @@ -729,12 +729,17 @@ static void aspeed_udc_ep_write(void *opaque, hwaddr offset, uint64_t data, case R_EP_DMA_STS: val &= 0x77ffffff; e->regs[reg] = val; - if (FIELD_EX32(e->regs[R_EP_DMA_CTRL], EP_DMA_CTRL, DESC_OP_EN)) { - /* IN, descriptor-list mode */ - aspeed_udc_ep_in_kick_desc(s, e->index, old_val); - } else { - /* OUT, single-stage mode */ + if (FIELD_EX32(e->regs[R_EP_CONFIG], EP_CONFIG, DIR_OUT)) { + if (FIELD_EX32(e->regs[R_EP_DMA_CTRL], EP_DMA_CTRL, DESC_OP_EN)) { + qemu_log_mask(LOG_UNIMP, "%s: ep %d OUT descriptor mode is not" + " implemented\n", __func__, e->index); + break; + } aspeed_udc_ep_out_kick_single(s, e->index); + } else { + if (FIELD_EX32(e->regs[R_EP_DMA_CTRL], EP_DMA_CTRL, DESC_OP_EN)) { + aspeed_udc_ep_in_kick_desc(s, e->index, old_val); + } } break; default: -- 2.53.0
