diff options
author | Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> | 2024-03-13 12:20:03 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-03-26 12:44:53 +0300 |
commit | 4483ef3c1685290251f7caf18377f793e0901460 (patch) | |
tree | 37c1534da6bba7bd90ff1d6d6cdb3d2510c28c0d | |
parent | 535a88dc7d61b740bba4fdbe2b0b5a517d8d1820 (diff) | |
download | linux-4483ef3c1685290251f7caf18377f793e0901460.tar.xz |
usb: dwc2: Add hibernation updates for ULPI PHY
Added programmming of ULPI_LATCH_EN_DURING_HIB_ENTRY bit in GPWRDN
register when using ULPI PHY during entry/exit to/from hibernation.
This bit set to 1 during entering to hibernation if ULPI PHY used.
On exiting from hibernation this bit reset to 0.
Applicable for both host and device modes.
Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Link: https://lore.kernel.org/r/e024cb39a7177ec201c873df25ca6365f2e55947.1708948356.git.Minas.Harutyunyan@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/dwc2/core.c | 5 | ||||
-rw-r--r-- | drivers/usb/dwc2/core_intr.c | 5 | ||||
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 23 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd.c | 10 |
4 files changed, 43 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 5635e4d7ec88..b7a76eb089c9 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -249,6 +249,11 @@ void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup, dwc2_writel(hsotg, gpwrdn, GPWRDN); udelay(10); + /* Reset ULPI latch */ + gpwrdn = dwc2_readl(hsotg, GPWRDN); + gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; + dwc2_writel(hsotg, gpwrdn, GPWRDN); + /* Disable PMU interrupt */ gpwrdn = dwc2_readl(hsotg, GPWRDN); gpwrdn &= ~GPWRDN_PMUINTSEL; diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index bb6bb771375a..aee779898c06 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -705,6 +705,11 @@ static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg, gpwrdn_tmp &= ~GPWRDN_PMUINTSEL; dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN); + /* Reset ULPI latch */ + gpwrdn = dwc2_readl(hsotg, GPWRDN); + gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; + dwc2_writel(hsotg, gpwrdn, GPWRDN); + /* De-assert Wakeup Logic */ gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN); gpwrdn_tmp &= ~GPWRDN_PMUACTV; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 680737d471c1..f67e69999e3e 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -5309,6 +5309,8 @@ void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg) { u32 gpwrdn; + u32 gusbcfg; + u32 pcgcctl; int ret = 0; /* Change to L2(suspend) state */ @@ -5328,6 +5330,22 @@ int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg) } gpwrdn = GPWRDN_PWRDNRSTN; + udelay(10); + gusbcfg = dwc2_readl(hsotg, GUSBCFG); + if (gusbcfg & GUSBCFG_ULPI_UTMI_SEL) { + /* ULPI interface */ + gpwrdn |= GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; + } + dwc2_writel(hsotg, gpwrdn, GPWRDN); + udelay(10); + + /* Suspend the Phy Clock */ + pcgcctl = dwc2_readl(hsotg, PCGCTL); + pcgcctl |= PCGCTL_STOPPCLK; + dwc2_writel(hsotg, pcgcctl, PCGCTL); + udelay(10); + + gpwrdn = dwc2_readl(hsotg, GPWRDN); gpwrdn |= GPWRDN_PMUACTV; dwc2_writel(hsotg, gpwrdn, GPWRDN); udelay(10); @@ -5428,6 +5446,11 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg, if (reset) dwc2_clear_bit(hsotg, DCFG, DCFG_DEVADDR_MASK); + /* Reset ULPI latch */ + gpwrdn = dwc2_readl(hsotg, GPWRDN); + gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; + dwc2_writel(hsotg, gpwrdn, GPWRDN); + /* De-assert Wakeup Logic */ gpwrdn = dwc2_readl(hsotg, GPWRDN); gpwrdn &= ~GPWRDN_PMUACTV; diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 35c7a4df8e71..cc75a7062910 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -5503,6 +5503,11 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) gusbcfg = dwc2_readl(hsotg, GUSBCFG); if (gusbcfg & GUSBCFG_ULPI_UTMI_SEL) { /* ULPI interface */ + udelay(10); + gpwrdn = dwc2_readl(hsotg, GPWRDN); + gpwrdn |= GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; + dwc2_writel(hsotg, gpwrdn, GPWRDN); + udelay(10); /* Suspend the Phy Clock */ pcgcctl = dwc2_readl(hsotg, PCGCTL); pcgcctl |= PCGCTL_STOPPCLK; @@ -5609,6 +5614,11 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG); dwc2_writel(hsotg, hr->hcfg, HCFG); + /* Reset ULPI latch */ + gpwrdn = dwc2_readl(hsotg, GPWRDN); + gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; + dwc2_writel(hsotg, gpwrdn, GPWRDN); + /* De-assert Wakeup Logic */ gpwrdn = dwc2_readl(hsotg, GPWRDN); gpwrdn &= ~GPWRDN_PMUACTV; |