diff options
author | Artur Petrosyan <Arthur.Petrosyan@synopsys.com> | 2021-04-16 16:47:22 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-04-22 11:55:33 +0200 |
commit | 4111d5f805d89cbf6c454357bf8782ba0387bb7c (patch) | |
tree | f68fbd5545c34eb850fb30f211a17caf44acbe3b | |
parent | 24d209dba5a3959b2ebde7cf3ad40c8015e814cf (diff) |
usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
When device cable is disconnected core receives suspend
interrupt and enters hibernation. After entering
into hibernation GPWRDN_RST_DET and GPWRDN_STS_CHGINT
interrupts are asserted.
Allowed exit from gadget hibernation from
GPWRDN_RST_DET by checking only linestate.
Changed the return type of "dwc2_handle_gpwrdn_intr()"
function from void to int because exit from hibernation
functions have a return value.
Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
Link: https://lore.kernel.org/r/20210416124723.B6F17A005C@mailhost.synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/dwc2/core_intr.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 27d729fad227..f8963c0cf6af 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -751,10 +751,11 @@ static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg, * The GPWRDN interrupts are those that occur in both Host and * Device mode while core is in hibernated state. */ -static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) +static int dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) { u32 gpwrdn; int linestate; + int ret = 0; gpwrdn = dwc2_readl(hsotg, GPWRDN); /* clear all interrupt */ @@ -778,17 +779,27 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) if (hsotg->hw_params.hibernation && hsotg->hibernated) { if (gpwrdn & GPWRDN_IDSTS) { - dwc2_exit_hibernation(hsotg, 0, 0, 0); + ret = dwc2_exit_hibernation(hsotg, 0, 0, 0); + if (ret) + dev_err(hsotg->dev, + "exit hibernation failed.\n"); call_gadget(hsotg, resume); } else { - dwc2_exit_hibernation(hsotg, 1, 0, 1); + ret = dwc2_exit_hibernation(hsotg, 1, 0, 1); + if (ret) + dev_err(hsotg->dev, + "exit hibernation failed.\n"); } } } 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 (!linestate) { + ret = dwc2_exit_hibernation(hsotg, 0, 1, 0); + if (ret) + dev_err(hsotg->dev, + "exit hibernation failed.\n"); + } } else if ((gpwrdn & GPWRDN_STS_CHGINT) && (gpwrdn & GPWRDN_STS_CHGINT_MSK)) { dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__); @@ -800,6 +811,8 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) */ dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn); } + + return ret; } /* |