return 0;
 }
 
+/**
+ * dwc_handle_gpwrdn_disc_det() - Handles the gpwrdn disconnect detect.
+ * Exits hibernation without restoring registers.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @gpwrdn: GPWRDN register
+ */
+static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
+                                             u32 gpwrdn)
+{
+       u32 gpwrdn_tmp;
+
+       /* Switch-on voltage to the core */
+       gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+       gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
+       dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+       udelay(5);
+
+       /* Reset core */
+       gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+       gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
+       dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+       udelay(5);
+
+       /* Disable Power Down Clamp */
+       gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+       gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
+       dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+       udelay(5);
+
+       /* Deassert reset core */
+       gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+       gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
+       dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+       udelay(5);
+
+       /* Disable PMU interrupt */
+       gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+       gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
+       dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+
+       /* De-assert Wakeup Logic */
+       gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+       gpwrdn_tmp &= ~GPWRDN_PMUACTV;
+       dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+
+       hsotg->hibernated = 0;
+       hsotg->bus_suspended = 0;
+
+       if (gpwrdn & GPWRDN_IDSTS) {
+               hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+               dwc2_core_init(hsotg, false);
+               dwc2_enable_global_interrupts(hsotg);
+               dwc2_hsotg_core_init_disconnected(hsotg, false);
+               dwc2_hsotg_core_connect(hsotg);
+       } else {
+               hsotg->op_state = OTG_STATE_A_HOST;
+
+               /* Initialize the Core for Host mode */
+               dwc2_core_init(hsotg, false);
+               dwc2_enable_global_interrupts(hsotg);
+               dwc2_hcd_start(hsotg);
+       }
+}
+
 /*
  * GPWRDN interrupt handler.
  *
 
        if ((gpwrdn & GPWRDN_DISCONN_DET) &&
            (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
-               u32 gpwrdn_tmp;
-
                dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
-
-               /* Switch-on voltage to the core */
-               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-               gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
-               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-               udelay(10);
-
-               /* Reset core */
-               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-               gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
-               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-               udelay(10);
-
-               /* Disable Power Down Clamp */
-               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-               gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
-               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-               udelay(10);
-
-               /* Deassert reset core */
-               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-               gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
-               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-               udelay(10);
-
-               /* Disable PMU interrupt */
-               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-               gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
-               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-
-               /* De-assert Wakeup Logic */
-               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-               gpwrdn_tmp &= ~GPWRDN_PMUACTV;
-               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-
-               hsotg->hibernated = 0;
-
-               if (gpwrdn & GPWRDN_IDSTS) {
-                       hsotg->op_state = OTG_STATE_B_PERIPHERAL;
-                       dwc2_core_init(hsotg, false);
-                       dwc2_enable_global_interrupts(hsotg);
-                       dwc2_hsotg_core_init_disconnected(hsotg, false);
-                       dwc2_hsotg_core_connect(hsotg);
-               } else {
-                       hsotg->op_state = OTG_STATE_A_HOST;
-
-                       /* Initialize the Core for Host mode */
-                       dwc2_core_init(hsotg, false);
-                       dwc2_enable_global_interrupts(hsotg);
-                       dwc2_hcd_start(hsotg);
-               }
-       }
-
-       if ((gpwrdn & GPWRDN_LNSTSCHG) &&
-           (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
+               /*
+                * Call disconnect detect function to exit from
+                * hibernation
+                */
+               dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
+       } else if ((gpwrdn & GPWRDN_LNSTSCHG) &&
+                  (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
                dev_dbg(hsotg->dev, "%s: GPWRDN_LNSTSCHG\n", __func__);
                if (hsotg->hw_params.hibernation &&
                    hsotg->hibernated) {
                                dwc2_exit_hibernation(hsotg, 1, 0, 1);
                        }
                }
-       }
-       if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) {
+       } else if ((gpwrdn & GPWRDN_RST_DET) &&
+                  (gpwrdn & GPWRDN_RST_DET_MSK)) {
                dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
                if (!linestate && (gpwrdn & GPWRDN_BSESSVLD))
                        dwc2_exit_hibernation(hsotg, 0, 1, 0);
-       }
-       if ((gpwrdn & GPWRDN_STS_CHGINT) &&
-           (gpwrdn & GPWRDN_STS_CHGINT_MSK) && linestate) {
+       } else if ((gpwrdn & GPWRDN_STS_CHGINT) &&
+                  (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
                dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
-               if (hsotg->hw_params.hibernation &&
-                   hsotg->hibernated) {
-                       if (gpwrdn & GPWRDN_IDSTS) {
-                               dwc2_exit_hibernation(hsotg, 0, 0, 0);
-                               call_gadget(hsotg, resume);
-                       } else {
-                               dwc2_exit_hibernation(hsotg, 1, 0, 1);
-                       }
-               }
+               /*
+                * As GPWRDN_STS_CHGINT exit from hibernation flow is
+                * the same as in GPWRDN_DISCONN_DET flow. Call
+                * disconnect detect helper function to exit from
+                * hibernation.
+                */
+               dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
        }
 }