Skip to content

[Backport v3.7.99-ncs3-branch] [nrf fromlist] drivers: udc_dwc2: Workaround hibernation exit glitch #2463

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions drivers/usb/common/usb_dwc2_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
#define USB_DWC2_GGPIO_STM32_PWRDWN_POS 16UL
#define USB_DWC2_GGPIO_STM32_PWRDWN BIT(USB_DWC2_GGPIO_STM32_PWRDWN_POS)

/* GSNPSID register */
#define USB_DWC2_GSNPSID_REV_5_00A 0x4F54500AUL

Check notice on line 343 in drivers/usb/common/usb_dwc2_hw.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/usb/common/usb_dwc2_hw.h:343 -#define USB_DWC2_GSNPSID_REV_5_00A 0x4F54500AUL +#define USB_DWC2_GSNPSID_REV_5_00A 0x4F54500AUL
/* GHWCFG1 register */
#define USB_DWC2_GHWCFG1 0x0044UL
#define USB_DWC2_GHWCFG1_EPDIR_POS(i) (i * 2)
Expand Down Expand Up @@ -997,7 +1000,34 @@

/* Power and Clock Gating Control Register */
#define USB_DWC2_PCGCCTL 0x0E00UL
#define USB_DWC2_PCGCCTL_IF_DEV_MODE_POS 31UL
#define USB_DWC2_PCGCCTL_IF_DEV_MODE BIT(USB_DWC2_PCGCCTL_IF_DEV_MODE_POS)
#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_POS 29UL
#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_MASK (0x3UL << USB_DWC2_PCGCCTL_P2HD_PRT_SPD_POS)
#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_LS 2
#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_FS 1
#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_HS 0
#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_POS 27UL
#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_MASK (0x3UL << USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_POS)
#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_FS48 3
#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_LS 2
#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_FS 1
#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_HS 0
#define USB_DWC2_PCGCCTL_MAC_DEV_ADDR_POS 20UL
#define USB_DWC2_PCGCCTL_MAC_DEV_ADDR_MASK (0x7FUL << USB_DWC2_PCGCCTL_MAC_DEV_ADDR_POS)
#define USB_DWC2_PCGCCTL_MAX_TERMSELECT_POS 19UL
#define USB_DWC2_PCGCCTL_MAX_TERMSELECT BIT(USB_DWC2_PCGCCTL_MAX_TERMSELECT_POS)
#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_POS 17UL
#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_MASK (0x3UL << USB_DWC2_PCGCCTL_MAC_XCVRSELECT_POS)
#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_LFS 3
#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_LS 2
#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_FS 1
#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_HS 0
#define USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0_POS 16UL
#define USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0 BIT(USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0_POS)
#define USB_DWC2_PCGCCTL_PRT_CLK_SEL_POS 14UL
#define USB_DWC2_PCGCCTL_PRT_CLK_SEL_MASK (0x3UL << USB_DWC2_PCGCCTL_PRT_CLK_SEL_POS)
#define USB_DWC2_PCGCCTL_RESTOREVALUE_POS 14UL

Check notice on line 1030 in drivers/usb/common/usb_dwc2_hw.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/usb/common/usb_dwc2_hw.h:1030 -#define USB_DWC2_PCGCCTL_IF_DEV_MODE_POS 31UL -#define USB_DWC2_PCGCCTL_IF_DEV_MODE BIT(USB_DWC2_PCGCCTL_IF_DEV_MODE_POS) -#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_POS 29UL -#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_MASK (0x3UL << USB_DWC2_PCGCCTL_P2HD_PRT_SPD_POS) -#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_LS 2 -#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_FS 1 -#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_HS 0 -#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_POS 27UL -#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_MASK (0x3UL << USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_POS) -#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_FS48 3 -#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_LS 2 -#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_FS 1 -#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_HS 0 -#define USB_DWC2_PCGCCTL_MAC_DEV_ADDR_POS 20UL -#define USB_DWC2_PCGCCTL_MAC_DEV_ADDR_MASK (0x7FUL << USB_DWC2_PCGCCTL_MAC_DEV_ADDR_POS) -#define USB_DWC2_PCGCCTL_MAX_TERMSELECT_POS 19UL -#define USB_DWC2_PCGCCTL_MAX_TERMSELECT BIT(USB_DWC2_PCGCCTL_MAX_TERMSELECT_POS) -#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_POS 17UL -#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_MASK (0x3UL << USB_DWC2_PCGCCTL_MAC_XCVRSELECT_POS) -#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_LFS 3 -#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_LS 2 -#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_FS 1 -#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_HS 0 -#define USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0_POS 16UL -#define USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0 BIT(USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0_POS) -#define USB_DWC2_PCGCCTL_PRT_CLK_SEL_POS 14UL -#define USB_DWC2_PCGCCTL_PRT_CLK_SEL_MASK (0x3UL << USB_DWC2_PCGCCTL_PRT_CLK_SEL_POS) +#define USB_DWC2_PCGCCTL_IF_DEV_MODE_POS 31UL +#define USB_DWC2_PCGCCTL_IF_DEV_MODE BIT(USB_DWC2_PCGCCTL_IF_DEV_MODE_POS) +#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_POS 29UL +#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_MASK (0x3UL << USB_DWC2_PCGCCTL_P2HD_PRT_SPD_POS) +#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_LS 2 +#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_FS 1 +#define USB_DWC2_PCGCCTL_P2HD_PRT_SPD_HS 0 +#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_POS 27UL +#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_MASK (0x3UL << USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_POS) +#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_FS48 3 +#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_LS 2 +#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_FS 1 +#define USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_HS 0 +#define USB_DWC2_PCGCCTL_MAC_DEV_ADDR_POS 20UL +#define USB_DWC2_PCGCCTL_MAC_DEV_ADDR_MASK (0x7FUL << USB_DWC2_PCGCCTL_MAC_DEV_ADDR_POS) +#define USB_DWC2_PCGCCTL_MAX_TERMSELECT_POS 19UL +#define USB_DWC2_PCGCCTL_MAX_TERMSELECT BIT(USB_DWC2_PCGCCTL_MAX_TERMSELECT_POS) +#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_POS 17UL +#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_MASK (0x3UL << USB_DWC2_PCGCCTL_MAC_XCVRSELECT_POS) +#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_LFS 3 +#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_LS 2 +#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_FS 1 +#define USB_DWC2_PCGCCTL_MAC_XCVRSELECT_HS 0 +#define USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0_POS 16UL +#define USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0 BIT(USB_DWC2_PCGCCTL_SH2PL_PRT_CTL0_POS) +#define USB_DWC2_PCGCCTL_PRT_CLK_SEL_POS 14UL +#define USB_DWC2_PCGCCTL_PRT_CLK_SEL_MASK (0x3UL << USB_DWC2_PCGCCTL_PRT_CLK_SEL_POS)
#define USB_DWC2_PCGCCTL_RESTOREVALUE_MASK (0x3FFFFUL << USB_DWC2_PCGCCTL_RESTOREVALUE_POS)
#define USB_DWC2_PCGCCTL_ESSREGRESTORED_POS 13UL
#define USB_DWC2_PCGCCTL_ESSREGRESTORED BIT(USB_DWC2_PCGCCTL_ESSREGRESTORED_POS)
Expand All @@ -1016,6 +1046,11 @@
#define USB_DWC2_PCGCCTL_STOPPCLK_POS 0UL
#define USB_DWC2_PCGCCTL_STOPPCLK BIT(USB_DWC2_PCGCCTL_STOPPCLK_POS)

USB_DWC2_GET_FIELD_DEFINE(pcgcctl_p2hd_prt_spd, PCGCCTL_P2HD_PRT_SPD)
USB_DWC2_GET_FIELD_DEFINE(pcgcctl_p2hd_dev_enum_spd, PCGCCTL_P2HD_DEV_ENUM_SPD)
USB_DWC2_GET_FIELD_DEFINE(pcgcctl_mac_dev_addr, PCGCCTL_MAC_DEV_ADDR)
USB_DWC2_GET_FIELD_DEFINE(pcgcctl_mac_xcvrselect, PCGCCTL_MAC_XCVRSELECT)
USB_DWC2_GET_FIELD_DEFINE(pcgcctl_prt_clk_sel, PCGCCTL_PRT_CLK_SEL)
USB_DWC2_GET_FIELD_DEFINE(pcgcctl_restorevalue, PCGCCTL_RESTOREVALUE)
USB_DWC2_SET_FIELD_DEFINE(pcgcctl_restorevalue, PCGCCTL_RESTOREVALUE)

Expand Down
35 changes: 27 additions & 8 deletions drivers/usb/udc/udc_dwc2.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@
unsigned int dynfifosizing : 1;
unsigned int bufferdma : 1;
unsigned int syncrst : 1;
/* Defect workarounds */
unsigned int wa_essregrestored : 1;
/* Runtime state flags */

Check notice on line 126 in drivers/usb/udc/udc_dwc2.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/usb/udc/udc_dwc2.c:126 - unsigned int wa_essregrestored : 1; + unsigned int wa_essregrestored: 1;
unsigned int hibernated : 1;
unsigned int enumdone : 1;
unsigned int enumspd : 2;
Expand Down Expand Up @@ -915,6 +917,11 @@
struct dwc2_reg_backup *backup = &priv->backup;
uint32_t pcgcctl = backup->pcgcctl & USB_DWC2_PCGCCTL_RESTOREVALUE_MASK;

if (usb_dwc2_get_pcgcctl_p2hd_dev_enum_spd(pcgcctl) ==
USB_DWC2_PCGCCTL_P2HD_DEV_ENUM_SPD_HS) {
pcgcctl |= BIT(17);
}

sys_write32(backup->glpmcfg, (mem_addr_t)&base->glpmcfg);
sys_write32(backup->gi2cctl, (mem_addr_t)&base->gi2cctl);
sys_write32(pcgcctl, (mem_addr_t)&base->pcgcctl);
Expand All @@ -940,6 +947,21 @@

pcgcctl |= USB_DWC2_PCGCCTL_ESSREGRESTORED;
sys_write32(pcgcctl, (mem_addr_t)&base->pcgcctl);

/* Note: in Remote Wakeup case 15 ms max signaling time starts now */

/* Wait for Restore Done Interrupt */
dwc2_wait_for_bit(dev, (mem_addr_t)&base->gintsts, USB_DWC2_GINTSTS_RSTRDONEINT);

if (priv->wa_essregrestored) {
pcgcctl &= ~USB_DWC2_PCGCCTL_ESSREGRESTORED;
sys_write32(pcgcctl, (mem_addr_t)&base->pcgcctl);
k_busy_wait(1);
}

if (!bus_reset) {
sys_write32(0xFFFFFFFFUL, (mem_addr_t)&base->gintsts);
}
}

static void dwc2_restore_device_registers(const struct device *dev, bool rwup)
Expand Down Expand Up @@ -1076,14 +1098,6 @@

dwc2_restore_essential_registers(dev, rwup, bus_reset);

/* Note: in Remote Wakeup case 15 ms max signaling time starts now */

/* Wait for Restore Done Interrupt */
dwc2_wait_for_bit(dev, (mem_addr_t)&base->gintsts, USB_DWC2_GINTSTS_RSTRDONEINT);
if (!bus_reset) {
sys_write32(0xFFFFFFFFUL, (mem_addr_t)&base->gintsts);
}

/* Disable restore from PMU */
sys_clear_bits(gpwrdn_reg, USB_DWC2_GPWRDN_RESTORE);
k_busy_wait(1);
Expand Down Expand Up @@ -1752,6 +1766,7 @@
mem_addr_t gahbcfg_reg = (mem_addr_t)&base->gahbcfg;
mem_addr_t gusbcfg_reg = (mem_addr_t)&base->gusbcfg;
mem_addr_t dcfg_reg = (mem_addr_t)&base->dcfg;
uint32_t gsnpsid;
uint32_t dcfg;
uint32_t gusbcfg;
uint32_t gahbcfg;
Expand All @@ -1767,6 +1782,10 @@
return ret;
}

/* Enable RTL workarounds based on controller revision */
gsnpsid = sys_read32((mem_addr_t)&base->gsnpsid);
priv->wa_essregrestored = gsnpsid < USB_DWC2_GSNPSID_REV_5_00A;

priv->ghwcfg1 = sys_read32((mem_addr_t)&base->ghwcfg1);
ghwcfg2 = sys_read32((mem_addr_t)&base->ghwcfg2);
ghwcfg3 = sys_read32((mem_addr_t)&base->ghwcfg3);
Expand Down
Loading