Skip to content

Commit 5fd2848

Browse files
committed
drivers: udc_dwc2: Fix deactivate when hibernated
It is possible for usbd_disable() to be called when the core is hibernated. When done so, the USB stack will attempt to deactivate all the endpoints. Because the core is hibernated, register reads are really undefined. This can lead to udc_dwc2_ep_deactivate() not calling udc_dwc2_ep_disable() which will leave struct udc_ep_config busy flag set. When endpoint 0x00 busy flag is left to true, the driver won't allocate buffer to receive SETUP data which is mandatory in Buffer DMA mode. This leads to essentially dead device after reconnect, because the device will not respond to any control transfers. Solve the issue by modifying backup register value instead of real one when endpoint is deactivated while core is hibernated. Signed-off-by: Tomasz Moń <[email protected]>
1 parent 7c82c06 commit 5fd2848

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

drivers/usb/udc/udc_dwc2.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,19 @@ static int udc_dwc2_ep_deactivate(const struct device *dev,
17331733
mem_addr_t dxepctl_reg;
17341734
uint32_t dxepctl;
17351735

1736-
dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr);
1736+
if (priv->hibernated) {
1737+
/* If usbd_disable() is called when core is hibernated, modify
1738+
* backup registers instead of real ones.
1739+
*/
1740+
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
1741+
dxepctl_reg = (mem_addr_t)&priv->backup.doepctl[ep_idx];
1742+
} else {
1743+
dxepctl_reg = (mem_addr_t)&priv->backup.diepctl[ep_idx];
1744+
}
1745+
} else {
1746+
dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr);
1747+
}
1748+
17371749
dxepctl = sys_read32(dxepctl_reg);
17381750

17391751
if (dxepctl & USB_DWC2_DEPCTL_USBACTEP) {

0 commit comments

Comments
 (0)