Skip to content

Commit 09fb10e

Browse files
tmon-nordicrlubos
authored andcommitted
[nrf fromlist] drivers: udc_dwc2: Abort wait when PHY is not clocked
On nRF54H20DK the USB PHY is powered from VBUS. When the USB cable is not connected, the PHY is not powered and the PHY clock disappears. Because the GOUTNAKEFF and INEPNAKEFF can only ever be set when PHY clock is active, the waits for these bits do timeout if cable is disconnected. Workaround the issue by aborting the wait if vendor quirk indicates that PHY clock has abruptly vanished. Upstream PR: zephyrproject-rtos/zephyr#73461 Signed-off-by: Tomasz Moń <[email protected]>
1 parent b1db11c commit 09fb10e

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

drivers/usb/udc/udc_dwc2.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,8 @@ static int dwc2_unset_dedicated_fifo(const struct device *dev,
11761176
return 0;
11771177
}
11781178

1179-
static void dwc2_wait_for_bit(mem_addr_t addr, uint32_t bit)
1179+
static void dwc2_wait_for_bit(const struct device *dev,
1180+
mem_addr_t addr, uint32_t bit)
11801181
{
11811182
k_timepoint_t timeout = sys_timepoint_calc(K_MSEC(100));
11821183

@@ -1187,6 +1188,13 @@ static void dwc2_wait_for_bit(mem_addr_t addr, uint32_t bit)
11871188
* Busy looping is most likely fine unless profiling shows otherwise.
11881189
*/
11891190
while (!(sys_read32(addr) & bit)) {
1191+
if (dwc2_quirk_is_phy_clk_off(dev)) {
1192+
/* No point in waiting, because the bit can only be set
1193+
* when the PHY is actively clocked.
1194+
*/
1195+
return;
1196+
}
1197+
11901198
if (sys_timepoint_expired(timeout)) {
11911199
LOG_ERR("Timeout waiting for bit 0x%08X at 0x%08X",
11921200
bit, (uint32_t)addr);
@@ -1241,7 +1249,7 @@ static void udc_dwc2_ep_disable(const struct device *dev,
12411249
dctl &= ~USB_DWC2_DCTL_SGOUTNAK;
12421250
}
12431251

1244-
dwc2_wait_for_bit(gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF);
1252+
dwc2_wait_for_bit(dev, gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF);
12451253

12461254
/* The application cannot disable control OUT endpoint 0. */
12471255
if (ep_idx != 0) {
@@ -1257,7 +1265,7 @@ static void udc_dwc2_ep_disable(const struct device *dev,
12571265
sys_write32(dxepctl, dxepctl_reg);
12581266

12591267
if (ep_idx != 0) {
1260-
dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD);
1268+
dwc2_wait_for_bit(dev, doepint_reg, USB_DWC2_DOEPINT_EPDISBLD);
12611269
}
12621270

12631271
/* Clear Endpoint Disabled interrupt */
@@ -1277,12 +1285,12 @@ static void udc_dwc2_ep_disable(const struct device *dev,
12771285
}
12781286
sys_write32(dxepctl, dxepctl_reg);
12791287

1280-
dwc2_wait_for_bit(diepint_reg, USB_DWC2_DIEPINT_INEPNAKEFF);
1288+
dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_INEPNAKEFF);
12811289

12821290
dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS;
12831291
sys_write32(dxepctl, dxepctl_reg);
12841292

1285-
dwc2_wait_for_bit(diepint_reg, USB_DWC2_DIEPINT_EPDISBLD);
1293+
dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_EPDISBLD);
12861294

12871295
/* Clear Endpoint Disabled interrupt */
12881296
sys_write32(USB_DWC2_DIEPINT_EPDISBLD, diepint_reg);

drivers/usb/udc/udc_dwc2.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ struct dwc2_vendor_quirks {
2828
int (*irq_clear)(const struct device *dev);
2929
/* Called on driver pre-init */
3030
int (*caps)(const struct device *dev);
31+
/* Called while waiting for bits that require PHY to be clocked */
32+
int (*is_phy_clk_off)(const struct device *dev);
3133
};
3234

3335
/* Driver configuration per instance */
@@ -69,5 +71,6 @@ DWC2_QUIRK_FUNC_DEFINE(disable)
6971
DWC2_QUIRK_FUNC_DEFINE(shutdown)
7072
DWC2_QUIRK_FUNC_DEFINE(irq_clear)
7173
DWC2_QUIRK_FUNC_DEFINE(caps)
74+
DWC2_QUIRK_FUNC_DEFINE(is_phy_clk_off)
7275

7376
#endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_H */

drivers/usb/udc/udc_dwc2_vendor_quirks.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ static inline int usbhs_init_caps(const struct device *dev)
244244
return 0;
245245
}
246246

247+
static inline int usbhs_is_phy_clk_off(const struct device *dev)
248+
{
249+
return !k_event_test(&usbhs_events, USBHS_VBUS_READY);
250+
}
251+
247252
#define QUIRK_NRF_USBHS_DEFINE(n) \
248253
struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \
249254
.init = usbhs_enable_nrfs_service, \
@@ -252,6 +257,7 @@ static inline int usbhs_init_caps(const struct device *dev)
252257
.shutdown = usbhs_disable_nrfs_service, \
253258
.irq_clear = usbhs_irq_clear, \
254259
.caps = usbhs_init_caps, \
260+
.is_phy_clk_off = usbhs_is_phy_clk_off, \
255261
};
256262

257263
DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE)

0 commit comments

Comments
 (0)