drivers: udc_dwc2: Fix timeouts when disabling endpoints
Do not set NAK bit again for endpoints that already have NAK bit set. Do not wait for OUT endpoint 0 disable because it cannot be disabled by application (DOEPCTL0 EPDis bit is Read-Only). Disable endpoints before disabling interrupts because it is necessary to handle RXFLVL interrupt (in Slave mode) for GOUTNAKEFF to become active. Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
This commit is contained in:
parent
63d4037e2f
commit
4db14f83e5
1 changed files with 21 additions and 5 deletions
|
@ -1258,6 +1258,16 @@ static void udc_dwc2_ep_disable(const struct device *dev,
|
|||
dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr);
|
||||
dxepctl = sys_read32(dxepctl_reg);
|
||||
|
||||
if (dxepctl & USB_DWC2_DEPCTL_NAKSTS) {
|
||||
/* Endpoint already sends forced NAKs. STALL if necessary. */
|
||||
if (stall) {
|
||||
dxepctl |= USB_DWC2_DEPCTL_STALL;
|
||||
sys_write32(dxepctl, dxepctl_reg);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
|
||||
mem_addr_t dctl_reg, gintsts_reg, doepint_reg;
|
||||
uint32_t dctl;
|
||||
|
@ -1278,7 +1288,11 @@ static void udc_dwc2_ep_disable(const struct device *dev,
|
|||
|
||||
dwc2_wait_for_bit(gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF);
|
||||
|
||||
dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS;
|
||||
/* The application cannot disable control OUT endpoint 0. */
|
||||
if (ep_idx != 0) {
|
||||
dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS;
|
||||
}
|
||||
|
||||
if (stall) {
|
||||
/* For OUT endpoints STALL is set instead of SNAK */
|
||||
dxepctl |= USB_DWC2_DEPCTL_STALL;
|
||||
|
@ -1287,7 +1301,9 @@ static void udc_dwc2_ep_disable(const struct device *dev,
|
|||
}
|
||||
sys_write32(dxepctl, dxepctl_reg);
|
||||
|
||||
dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD);
|
||||
if (ep_idx != 0) {
|
||||
dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD);
|
||||
}
|
||||
|
||||
/* Clear Endpoint Disabled interrupt */
|
||||
sys_write32(USB_DWC2_DIEPINT_EPDISBLD, doepint_reg);
|
||||
|
@ -1712,9 +1728,6 @@ static int udc_dwc2_disable(const struct device *dev)
|
|||
sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON);
|
||||
LOG_DBG("Disable device %p", dev);
|
||||
|
||||
config->irq_disable_func(dev);
|
||||
sys_clear_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK);
|
||||
|
||||
if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) {
|
||||
LOG_DBG("Failed to disable control endpoint");
|
||||
return -EIO;
|
||||
|
@ -1725,6 +1738,9 @@ static int udc_dwc2_disable(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
config->irq_disable_func(dev);
|
||||
sys_clear_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK);
|
||||
|
||||
err = dwc2_quirk_disable(dev);
|
||||
if (err) {
|
||||
LOG_ERR("Quirk disable failed %d", err);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue