Skip to content

Commit a940f9d

Browse files
tmon-nordiccarlescufi
authored andcommitted
[nrf fromtree] 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]> (cherry picked from commit 35620e20a91efb3284716698f2fa794d02ec6b97)
1 parent 0ec9400 commit a940f9d

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
@@ -1730,7 +1730,19 @@ static int udc_dwc2_ep_deactivate(const struct device *dev,
17301730
mem_addr_t dxepctl_reg;
17311731
uint32_t dxepctl;
17321732

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

17361748
if (dxepctl & USB_DWC2_DEPCTL_USBACTEP) {

0 commit comments

Comments
 (0)