usb: dwc2: Add hibernation updates for ULPI PHY
authorMinas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Wed, 13 Mar 2024 09:20:03 +0000 (09:20 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Mar 2024 09:44:53 +0000 (10:44 +0100)
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>
drivers/usb/dwc2/core.c
drivers/usb/dwc2/core_intr.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/hcd.c

index 5635e4d7ec880e70b80ee938ed8e732b10ea168e..b7a76eb089c9a132d80d32b6e1e70ff0aed0c616 100644 (file)
@@ -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;
index bb6bb771375aeedd9d50d768cda11d18f1d6e1a4..aee779898c069b935cb959fcd607cdeedf7141b7 100644 (file)
@@ -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;
index 680737d471c1280d87d89b1ccfbb48346345958d..f67e69999e3e3b2c88098e376c77e8e516ce80bd 100644 (file)
@@ -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;
index 35c7a4df8e71754f88d36f2f551d2e1e9eecef56..cc75a7062910468a4d563863cf9d6f51f3acb4a0 100644 (file)
@@ -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;