From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S939815AbdD1ItY (ORCPT ); Fri, 28 Apr 2017 04:49:24 -0400 Received: from smtprelay4.synopsys.com ([198.182.47.9]:44261 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S939263AbdD1Isb (ORCPT ); Fri, 28 Apr 2017 04:48:31 -0400 Date: Fri, 28 Apr 2017 12:48:12 +0400 Message-ID: <4efc689082dcefefbea0b4a3c6da10091ef5afd2.1493369198.git.sevaka@synopsys.com> In-Reply-To: References: From: Sevak Arakelyan Subject: [PATCH 4/9] usb: dwc2: gadget: LPM interrupt handler To: John Youn , Felipe Balbi , "Greg Kroah-Hartman" , , CC: Sevak Arakelyan MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.13.184.19] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This interrupt indicates that an LPM transaction was received on the USB bus. After getting this interrupt we are going from L0 state to L1 state. Signed-off-by: Sevak Arakelyan --- drivers/usb/dwc2/core_intr.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index c7dd764fbfa9..663d56a293af 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -527,6 +527,64 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) } } +/** + * dwc2_handle_lpm_intr - GINTSTS_LPMTRANRCVD Interrupt handler + */ +static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg) +{ + u32 glpmcfg; + u32 pcgcctl; + u32 hird; + u32 hird_thres; + u32 hird_thres_en; + u32 enslpm; + + /* Clear interrupt */ + dwc2_writel(GINTSTS_LPMTRANRCVD, hsotg->regs + GINTSTS); + + glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG); + + if (!(glpmcfg & GLPMCFG_LPMCAP)) { + dev_err(hsotg->dev, "Unexpected LPM interrupt\n"); + return; + } + + hird = (glpmcfg & GLPMCFG_HIRD_MASK) >> GLPMCFG_HIRD_SHIFT; + hird_thres = (glpmcfg & GLPMCFG_HIRD_MASK & ~GLPMCFG_HIRD_THRES_EN) >> + GLPMCFG_HIRD_THRES_SHIFT; + hird_thres_en = glpmcfg & GLPMCFG_HIRD_THRES_EN; + enslpm = glpmcfg & GLPMCFG_SNDLPM; + + if (dwc2_is_device_mode(hsotg)) { + dev_dbg(hsotg->dev, "HIRD_THRES_EN = %d\n", hird_thres_en); + + if (hird_thres_en && hird >= hird_thres) { + dev_dbg(hsotg->dev, "L1 with utmi_l1_suspend_n\n"); + } else if (enslpm) { + dev_dbg(hsotg->dev, "L1 with utmi_sleep_n\n"); + } else { + dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n"); + + pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); + pcgcctl |= PCGCTL_ENBL_SLEEP_GATING; + dwc2_writel(pcgcctl, hsotg->regs + PCGCTL); + } + /** + * Examine prt_sleep_sts after TL1TokenTetry period max (10 us) + */ + udelay(10); + + glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG); + + if (glpmcfg && GLPMCFG_SLPSTS) { + /* Save the current state */ + hsotg->lx_state = DWC2_L1; + dev_dbg(hsotg->dev, + "Core is in L1 sleep glpmcfg=%08x\n", glpmcfg); + } + } +} + #define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \ GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT | \ GINTSTS_MODEMIS | GINTSTS_DISCONNINT | \ @@ -601,6 +659,8 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev) dwc2_handle_wakeup_detected_intr(hsotg); if (gintsts & GINTSTS_USBSUSP) dwc2_handle_usb_suspend_intr(hsotg); + if (gintsts & GINTSTS_LPMTRANRCVD) + dwc2_handle_lpm_intr(hsotg); if (gintsts & GINTSTS_PRTINT) { /* -- 2.11.0