Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 /*
0003  * core_intr.c - DesignWare HS OTG Controller common interrupt handling
0004  *
0005  * Copyright (C) 2004-2013 Synopsys, Inc.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions, and the following disclaimer,
0012  *    without modification.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  * 3. The names of the above-listed copyright holders may not be used
0017  *    to endorse or promote products derived from this software without
0018  *    specific prior written permission.
0019  *
0020  * ALTERNATIVELY, this software may be distributed under the terms of the
0021  * GNU General Public License ("GPL") as published by the Free Software
0022  * Foundation; either version 2 of the License, or (at your option) any
0023  * later version.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0026  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0027  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0028  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0029  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0030  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0031  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0032  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0033  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0034  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0035  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 /*
0039  * This file contains the common interrupt handlers
0040  */
0041 #include <linux/kernel.h>
0042 #include <linux/module.h>
0043 #include <linux/moduleparam.h>
0044 #include <linux/spinlock.h>
0045 #include <linux/interrupt.h>
0046 #include <linux/dma-mapping.h>
0047 #include <linux/io.h>
0048 #include <linux/slab.h>
0049 #include <linux/usb.h>
0050 
0051 #include <linux/usb/hcd.h>
0052 #include <linux/usb/ch11.h>
0053 
0054 #include "core.h"
0055 #include "hcd.h"
0056 
0057 static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
0058 {
0059     switch (hsotg->op_state) {
0060     case OTG_STATE_A_HOST:
0061         return "a_host";
0062     case OTG_STATE_A_SUSPEND:
0063         return "a_suspend";
0064     case OTG_STATE_A_PERIPHERAL:
0065         return "a_peripheral";
0066     case OTG_STATE_B_PERIPHERAL:
0067         return "b_peripheral";
0068     case OTG_STATE_B_HOST:
0069         return "b_host";
0070     default:
0071         return "unknown";
0072     }
0073 }
0074 
0075 /**
0076  * dwc2_handle_usb_port_intr - handles OTG PRTINT interrupts.
0077  * When the PRTINT interrupt fires, there are certain status bits in the Host
0078  * Port that needs to get cleared.
0079  *
0080  * @hsotg: Programming view of DWC_otg controller
0081  */
0082 static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
0083 {
0084     u32 hprt0 = dwc2_readl(hsotg, HPRT0);
0085 
0086     if (hprt0 & HPRT0_ENACHG) {
0087         hprt0 &= ~HPRT0_ENA;
0088         dwc2_writel(hsotg, hprt0, HPRT0);
0089     }
0090 }
0091 
0092 /**
0093  * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
0094  *
0095  * @hsotg: Programming view of DWC_otg controller
0096  */
0097 static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
0098 {
0099     /* Clear interrupt */
0100     dwc2_writel(hsotg, GINTSTS_MODEMIS, GINTSTS);
0101 
0102     dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
0103          dwc2_is_host_mode(hsotg) ? "Host" : "Device");
0104 }
0105 
0106 /**
0107  * dwc2_handle_otg_intr() - Handles the OTG Interrupts. It reads the OTG
0108  * Interrupt Register (GOTGINT) to determine what interrupt has occurred.
0109  *
0110  * @hsotg: Programming view of DWC_otg controller
0111  */
0112 static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
0113 {
0114     u32 gotgint;
0115     u32 gotgctl;
0116     u32 gintmsk;
0117 
0118     gotgint = dwc2_readl(hsotg, GOTGINT);
0119     gotgctl = dwc2_readl(hsotg, GOTGCTL);
0120     dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
0121         dwc2_op_state_str(hsotg));
0122 
0123     if (gotgint & GOTGINT_SES_END_DET) {
0124         dev_dbg(hsotg->dev,
0125             " ++OTG Interrupt: Session End Detected++ (%s)\n",
0126             dwc2_op_state_str(hsotg));
0127         gotgctl = dwc2_readl(hsotg, GOTGCTL);
0128 
0129         if (dwc2_is_device_mode(hsotg))
0130             dwc2_hsotg_disconnect(hsotg);
0131 
0132         if (hsotg->op_state == OTG_STATE_B_HOST) {
0133             hsotg->op_state = OTG_STATE_B_PERIPHERAL;
0134         } else {
0135             /*
0136              * If not B_HOST and Device HNP still set, HNP did
0137              * not succeed!
0138              */
0139             if (gotgctl & GOTGCTL_DEVHNPEN) {
0140                 dev_dbg(hsotg->dev, "Session End Detected\n");
0141                 dev_err(hsotg->dev,
0142                     "Device Not Connected/Responding!\n");
0143             }
0144 
0145             /*
0146              * If Session End Detected the B-Cable has been
0147              * disconnected
0148              */
0149             /* Reset to a clean state */
0150             hsotg->lx_state = DWC2_L0;
0151         }
0152 
0153         gotgctl = dwc2_readl(hsotg, GOTGCTL);
0154         gotgctl &= ~GOTGCTL_DEVHNPEN;
0155         dwc2_writel(hsotg, gotgctl, GOTGCTL);
0156     }
0157 
0158     if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
0159         dev_dbg(hsotg->dev,
0160             " ++OTG Interrupt: Session Request Success Status Change++\n");
0161         gotgctl = dwc2_readl(hsotg, GOTGCTL);
0162         if (gotgctl & GOTGCTL_SESREQSCS) {
0163             if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
0164                 hsotg->params.i2c_enable) {
0165                 hsotg->srp_success = 1;
0166             } else {
0167                 /* Clear Session Request */
0168                 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0169                 gotgctl &= ~GOTGCTL_SESREQ;
0170                 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0171             }
0172         }
0173     }
0174 
0175     if (gotgint & GOTGINT_HST_NEG_SUC_STS_CHNG) {
0176         /*
0177          * Print statements during the HNP interrupt handling
0178          * can cause it to fail
0179          */
0180         gotgctl = dwc2_readl(hsotg, GOTGCTL);
0181         /*
0182          * WA for 3.00a- HW is not setting cur_mode, even sometimes
0183          * this does not help
0184          */
0185         if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)
0186             udelay(100);
0187         if (gotgctl & GOTGCTL_HSTNEGSCS) {
0188             if (dwc2_is_host_mode(hsotg)) {
0189                 hsotg->op_state = OTG_STATE_B_HOST;
0190                 /*
0191                  * Need to disable SOF interrupt immediately.
0192                  * When switching from device to host, the PCD
0193                  * interrupt handler won't handle the interrupt
0194                  * if host mode is already set. The HCD
0195                  * interrupt handler won't get called if the
0196                  * HCD state is HALT. This means that the
0197                  * interrupt does not get handled and Linux
0198                  * complains loudly.
0199                  */
0200                 gintmsk = dwc2_readl(hsotg, GINTMSK);
0201                 gintmsk &= ~GINTSTS_SOF;
0202                 dwc2_writel(hsotg, gintmsk, GINTMSK);
0203 
0204                 /*
0205                  * Call callback function with spin lock
0206                  * released
0207                  */
0208                 spin_unlock(&hsotg->lock);
0209 
0210                 /* Initialize the Core for Host mode */
0211                 dwc2_hcd_start(hsotg);
0212                 spin_lock(&hsotg->lock);
0213                 hsotg->op_state = OTG_STATE_B_HOST;
0214             }
0215         } else {
0216             gotgctl = dwc2_readl(hsotg, GOTGCTL);
0217             gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
0218             dwc2_writel(hsotg, gotgctl, GOTGCTL);
0219             dev_dbg(hsotg->dev, "HNP Failed\n");
0220             dev_err(hsotg->dev,
0221                 "Device Not Connected/Responding\n");
0222         }
0223     }
0224 
0225     if (gotgint & GOTGINT_HST_NEG_DET) {
0226         /*
0227          * The disconnect interrupt is set at the same time as
0228          * Host Negotiation Detected. During the mode switch all
0229          * interrupts are cleared so the disconnect interrupt
0230          * handler will not get executed.
0231          */
0232         dev_dbg(hsotg->dev,
0233             " ++OTG Interrupt: Host Negotiation Detected++ (%s)\n",
0234             (dwc2_is_host_mode(hsotg) ? "Host" : "Device"));
0235         if (dwc2_is_device_mode(hsotg)) {
0236             dev_dbg(hsotg->dev, "a_suspend->a_peripheral (%d)\n",
0237                 hsotg->op_state);
0238             spin_unlock(&hsotg->lock);
0239             dwc2_hcd_disconnect(hsotg, false);
0240             spin_lock(&hsotg->lock);
0241             hsotg->op_state = OTG_STATE_A_PERIPHERAL;
0242         } else {
0243             /* Need to disable SOF interrupt immediately */
0244             gintmsk = dwc2_readl(hsotg, GINTMSK);
0245             gintmsk &= ~GINTSTS_SOF;
0246             dwc2_writel(hsotg, gintmsk, GINTMSK);
0247             spin_unlock(&hsotg->lock);
0248             dwc2_hcd_start(hsotg);
0249             spin_lock(&hsotg->lock);
0250             hsotg->op_state = OTG_STATE_A_HOST;
0251         }
0252     }
0253 
0254     if (gotgint & GOTGINT_A_DEV_TOUT_CHG)
0255         dev_dbg(hsotg->dev,
0256             " ++OTG Interrupt: A-Device Timeout Change++\n");
0257     if (gotgint & GOTGINT_DBNCE_DONE)
0258         dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
0259 
0260     /* Clear GOTGINT */
0261     dwc2_writel(hsotg, gotgint, GOTGINT);
0262 }
0263 
0264 /**
0265  * dwc2_handle_conn_id_status_change_intr() - Handles the Connector ID Status
0266  * Change Interrupt
0267  *
0268  * @hsotg: Programming view of DWC_otg controller
0269  *
0270  * Reads the OTG Interrupt Register (GOTCTL) to determine whether this is a
0271  * Device to Host Mode transition or a Host to Device Mode transition. This only
0272  * occurs when the cable is connected/removed from the PHY connector.
0273  */
0274 static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
0275 {
0276     u32 gintmsk;
0277 
0278     /* Clear interrupt */
0279     dwc2_writel(hsotg, GINTSTS_CONIDSTSCHNG, GINTSTS);
0280 
0281     /* Need to disable SOF interrupt immediately */
0282     gintmsk = dwc2_readl(hsotg, GINTMSK);
0283     gintmsk &= ~GINTSTS_SOF;
0284     dwc2_writel(hsotg, gintmsk, GINTMSK);
0285 
0286     dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
0287         dwc2_is_host_mode(hsotg) ? "Host" : "Device");
0288 
0289     /*
0290      * Need to schedule a work, as there are possible DELAY function calls.
0291      */
0292     if (hsotg->wq_otg)
0293         queue_work(hsotg->wq_otg, &hsotg->wf_otg);
0294 }
0295 
0296 /**
0297  * dwc2_handle_session_req_intr() - This interrupt indicates that a device is
0298  * initiating the Session Request Protocol to request the host to turn on bus
0299  * power so a new session can begin
0300  *
0301  * @hsotg: Programming view of DWC_otg controller
0302  *
0303  * This handler responds by turning on bus power. If the DWC_otg controller is
0304  * in low power mode, this handler brings the controller out of low power mode
0305  * before turning on bus power.
0306  */
0307 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
0308 {
0309     int ret;
0310     u32 hprt0;
0311 
0312     /* Clear interrupt */
0313     dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
0314 
0315     dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
0316         hsotg->lx_state);
0317 
0318     if (dwc2_is_device_mode(hsotg)) {
0319         if (hsotg->lx_state == DWC2_L2) {
0320             if (hsotg->in_ppd) {
0321                 ret = dwc2_exit_partial_power_down(hsotg, 0,
0322                                    true);
0323                 if (ret)
0324                     dev_err(hsotg->dev,
0325                         "exit power_down failed\n");
0326             }
0327 
0328             /* Exit gadget mode clock gating. */
0329             if (hsotg->params.power_down ==
0330                 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
0331                 dwc2_gadget_exit_clock_gating(hsotg, 0);
0332         }
0333 
0334         /*
0335          * Report disconnect if there is any previous session
0336          * established
0337          */
0338         dwc2_hsotg_disconnect(hsotg);
0339     } else {
0340         /* Turn on the port power bit. */
0341         hprt0 = dwc2_read_hprt0(hsotg);
0342         hprt0 |= HPRT0_PWR;
0343         dwc2_writel(hsotg, hprt0, HPRT0);
0344         /* Connect hcd after port power is set. */
0345         dwc2_hcd_connect(hsotg);
0346     }
0347 }
0348 
0349 /**
0350  * dwc2_wakeup_from_lpm_l1 - Exit the device from LPM L1 state
0351  *
0352  * @hsotg: Programming view of DWC_otg controller
0353  *
0354  */
0355 static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
0356 {
0357     u32 glpmcfg;
0358     u32 i = 0;
0359 
0360     if (hsotg->lx_state != DWC2_L1) {
0361         dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
0362         return;
0363     }
0364 
0365     glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0366     if (dwc2_is_device_mode(hsotg)) {
0367         dev_dbg(hsotg->dev, "Exit from L1 state\n");
0368         glpmcfg &= ~GLPMCFG_ENBLSLPM;
0369         glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
0370         dwc2_writel(hsotg, glpmcfg, GLPMCFG);
0371 
0372         do {
0373             glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0374 
0375             if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
0376                      GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
0377                 break;
0378 
0379             udelay(1);
0380         } while (++i < 200);
0381 
0382         if (i == 200) {
0383             dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
0384             return;
0385         }
0386         dwc2_gadget_init_lpm(hsotg);
0387     } else {
0388         /* TODO */
0389         dev_err(hsotg->dev, "Host side LPM is not supported.\n");
0390         return;
0391     }
0392 
0393     /* Change to L0 state */
0394     hsotg->lx_state = DWC2_L0;
0395 
0396     /* Inform gadget to exit from L1 */
0397     call_gadget(hsotg, resume);
0398 }
0399 
0400 /*
0401  * This interrupt indicates that the DWC_otg controller has detected a
0402  * resume or remote wakeup sequence. If the DWC_otg controller is in
0403  * low power mode, the handler must brings the controller out of low
0404  * power mode. The controller automatically begins resume signaling.
0405  * The handler schedules a time to stop resume signaling.
0406  */
0407 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
0408 {
0409     int ret;
0410 
0411     /* Clear interrupt */
0412     dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
0413 
0414     dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
0415     dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
0416 
0417     if (hsotg->lx_state == DWC2_L1) {
0418         dwc2_wakeup_from_lpm_l1(hsotg);
0419         return;
0420     }
0421 
0422     if (dwc2_is_device_mode(hsotg)) {
0423         dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
0424             dwc2_readl(hsotg, DSTS));
0425         if (hsotg->lx_state == DWC2_L2) {
0426             if (hsotg->in_ppd) {
0427                 u32 dctl = dwc2_readl(hsotg, DCTL);
0428                 /* Clear Remote Wakeup Signaling */
0429                 dctl &= ~DCTL_RMTWKUPSIG;
0430                 dwc2_writel(hsotg, dctl, DCTL);
0431                 ret = dwc2_exit_partial_power_down(hsotg, 1,
0432                                    true);
0433                 if (ret)
0434                     dev_err(hsotg->dev,
0435                         "exit partial_power_down failed\n");
0436                 call_gadget(hsotg, resume);
0437             }
0438 
0439             /* Exit gadget mode clock gating. */
0440             if (hsotg->params.power_down ==
0441                 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
0442                 dwc2_gadget_exit_clock_gating(hsotg, 0);
0443         } else {
0444             /* Change to L0 state */
0445             hsotg->lx_state = DWC2_L0;
0446         }
0447     } else {
0448         if (hsotg->lx_state == DWC2_L2) {
0449             if (hsotg->in_ppd) {
0450                 ret = dwc2_exit_partial_power_down(hsotg, 1,
0451                                    true);
0452                 if (ret)
0453                     dev_err(hsotg->dev,
0454                         "exit partial_power_down failed\n");
0455             }
0456 
0457             if (hsotg->params.power_down ==
0458                 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
0459                 dwc2_host_exit_clock_gating(hsotg, 1);
0460 
0461             /*
0462              * If we've got this quirk then the PHY is stuck upon
0463              * wakeup.  Assert reset.  This will propagate out and
0464              * eventually we'll re-enumerate the device.  Not great
0465              * but the best we can do.  We can't call phy_reset()
0466              * at interrupt time but there's no hurry, so we'll
0467              * schedule it for later.
0468              */
0469             if (hsotg->reset_phy_on_wake)
0470                 dwc2_host_schedule_phy_reset(hsotg);
0471 
0472             mod_timer(&hsotg->wkp_timer,
0473                   jiffies + msecs_to_jiffies(71));
0474         } else {
0475             /* Change to L0 state */
0476             hsotg->lx_state = DWC2_L0;
0477         }
0478     }
0479 }
0480 
0481 /*
0482  * This interrupt indicates that a device has been disconnected from the
0483  * root port
0484  */
0485 static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
0486 {
0487     dwc2_writel(hsotg, GINTSTS_DISCONNINT, GINTSTS);
0488 
0489     dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
0490         dwc2_is_host_mode(hsotg) ? "Host" : "Device",
0491         dwc2_op_state_str(hsotg));
0492 
0493     if (hsotg->op_state == OTG_STATE_A_HOST)
0494         dwc2_hcd_disconnect(hsotg, false);
0495 }
0496 
0497 /*
0498  * This interrupt indicates that SUSPEND state has been detected on the USB.
0499  *
0500  * For HNP the USB Suspend interrupt signals the change from "a_peripheral"
0501  * to "a_host".
0502  *
0503  * When power management is enabled the core will be put in low power mode.
0504  */
0505 static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
0506 {
0507     u32 dsts;
0508     int ret;
0509 
0510     /* Clear interrupt */
0511     dwc2_writel(hsotg, GINTSTS_USBSUSP, GINTSTS);
0512 
0513     dev_dbg(hsotg->dev, "USB SUSPEND\n");
0514 
0515     if (dwc2_is_device_mode(hsotg)) {
0516         /*
0517          * Check the Device status register to determine if the Suspend
0518          * state is active
0519          */
0520         dsts = dwc2_readl(hsotg, DSTS);
0521         dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
0522         dev_dbg(hsotg->dev,
0523             "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d HWCFG4.Hibernation=%d\n",
0524             !!(dsts & DSTS_SUSPSTS),
0525             hsotg->hw_params.power_optimized,
0526             hsotg->hw_params.hibernation);
0527 
0528         /* Ignore suspend request before enumeration */
0529         if (!dwc2_is_device_connected(hsotg)) {
0530             dev_dbg(hsotg->dev,
0531                 "ignore suspend request before enumeration\n");
0532             return;
0533         }
0534         if (dsts & DSTS_SUSPSTS) {
0535             switch (hsotg->params.power_down) {
0536             case DWC2_POWER_DOWN_PARAM_PARTIAL:
0537                 ret = dwc2_enter_partial_power_down(hsotg);
0538                 if (ret)
0539                     dev_err(hsotg->dev,
0540                         "enter partial_power_down failed\n");
0541 
0542                 udelay(100);
0543 
0544                 /* Ask phy to be suspended */
0545                 if (!IS_ERR_OR_NULL(hsotg->uphy))
0546                     usb_phy_set_suspend(hsotg->uphy, true);
0547                 break;
0548             case DWC2_POWER_DOWN_PARAM_HIBERNATION:
0549                 ret = dwc2_enter_hibernation(hsotg, 0);
0550                 if (ret)
0551                     dev_err(hsotg->dev,
0552                         "enter hibernation failed\n");
0553                 break;
0554             case DWC2_POWER_DOWN_PARAM_NONE:
0555                 /*
0556                  * If neither hibernation nor partial power down are supported,
0557                  * clock gating is used to save power.
0558                  */
0559                 if (!hsotg->params.no_clock_gating)
0560                     dwc2_gadget_enter_clock_gating(hsotg);
0561             }
0562 
0563             /*
0564              * Change to L2 (suspend) state before releasing
0565              * spinlock
0566              */
0567             hsotg->lx_state = DWC2_L2;
0568 
0569             /* Call gadget suspend callback */
0570             call_gadget(hsotg, suspend);
0571         }
0572     } else {
0573         if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
0574             dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
0575 
0576             /* Change to L2 (suspend) state */
0577             hsotg->lx_state = DWC2_L2;
0578             /* Clear the a_peripheral flag, back to a_host */
0579             spin_unlock(&hsotg->lock);
0580             dwc2_hcd_start(hsotg);
0581             spin_lock(&hsotg->lock);
0582             hsotg->op_state = OTG_STATE_A_HOST;
0583         }
0584     }
0585 }
0586 
0587 /**
0588  * dwc2_handle_lpm_intr - GINTSTS_LPMTRANRCVD Interrupt handler
0589  *
0590  * @hsotg: Programming view of DWC_otg controller
0591  *
0592  */
0593 static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
0594 {
0595     u32 glpmcfg;
0596     u32 pcgcctl;
0597     u32 hird;
0598     u32 hird_thres;
0599     u32 hird_thres_en;
0600     u32 enslpm;
0601 
0602     /* Clear interrupt */
0603     dwc2_writel(hsotg, GINTSTS_LPMTRANRCVD, GINTSTS);
0604 
0605     glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0606 
0607     if (!(glpmcfg & GLPMCFG_LPMCAP)) {
0608         dev_err(hsotg->dev, "Unexpected LPM interrupt\n");
0609         return;
0610     }
0611 
0612     hird = (glpmcfg & GLPMCFG_HIRD_MASK) >> GLPMCFG_HIRD_SHIFT;
0613     hird_thres = (glpmcfg & GLPMCFG_HIRD_THRES_MASK &
0614             ~GLPMCFG_HIRD_THRES_EN) >> GLPMCFG_HIRD_THRES_SHIFT;
0615     hird_thres_en = glpmcfg & GLPMCFG_HIRD_THRES_EN;
0616     enslpm = glpmcfg & GLPMCFG_ENBLSLPM;
0617 
0618     if (dwc2_is_device_mode(hsotg)) {
0619         dev_dbg(hsotg->dev, "HIRD_THRES_EN = %d\n", hird_thres_en);
0620 
0621         if (hird_thres_en && hird >= hird_thres) {
0622             dev_dbg(hsotg->dev, "L1 with utmi_l1_suspend_n\n");
0623         } else if (enslpm) {
0624             dev_dbg(hsotg->dev, "L1 with utmi_sleep_n\n");
0625         } else {
0626             dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n");
0627 
0628             pcgcctl = dwc2_readl(hsotg, PCGCTL);
0629             pcgcctl |= PCGCTL_ENBL_SLEEP_GATING;
0630             dwc2_writel(hsotg, pcgcctl, PCGCTL);
0631         }
0632         /**
0633          * Examine prt_sleep_sts after TL1TokenTetry period max (10 us)
0634          */
0635         udelay(10);
0636 
0637         glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0638 
0639         if (glpmcfg & GLPMCFG_SLPSTS) {
0640             /* Save the current state */
0641             hsotg->lx_state = DWC2_L1;
0642             dev_dbg(hsotg->dev,
0643                 "Core is in L1 sleep glpmcfg=%08x\n", glpmcfg);
0644 
0645             /* Inform gadget that we are in L1 state */
0646             call_gadget(hsotg, suspend);
0647         }
0648     }
0649 }
0650 
0651 #define GINTMSK_COMMON  (GINTSTS_WKUPINT | GINTSTS_SESSREQINT |     \
0652              GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT |    \
0653              GINTSTS_MODEMIS | GINTSTS_DISCONNINT |     \
0654              GINTSTS_USBSUSP | GINTSTS_PRTINT |     \
0655              GINTSTS_LPMTRANRCVD)
0656 
0657 /*
0658  * This function returns the Core Interrupt register
0659  */
0660 static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
0661 {
0662     u32 gintsts;
0663     u32 gintmsk;
0664     u32 gahbcfg;
0665     u32 gintmsk_common = GINTMSK_COMMON;
0666 
0667     gintsts = dwc2_readl(hsotg, GINTSTS);
0668     gintmsk = dwc2_readl(hsotg, GINTMSK);
0669     gahbcfg = dwc2_readl(hsotg, GAHBCFG);
0670 
0671     /* If any common interrupts set */
0672     if (gintsts & gintmsk_common)
0673         dev_dbg(hsotg->dev, "gintsts=%08x  gintmsk=%08x\n",
0674             gintsts, gintmsk);
0675 
0676     if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
0677         return gintsts & gintmsk & gintmsk_common;
0678     else
0679         return 0;
0680 }
0681 
0682 /**
0683  * dwc_handle_gpwrdn_disc_det() - Handles the gpwrdn disconnect detect.
0684  * Exits hibernation without restoring registers.
0685  *
0686  * @hsotg: Programming view of DWC_otg controller
0687  * @gpwrdn: GPWRDN register
0688  */
0689 static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
0690                           u32 gpwrdn)
0691 {
0692     u32 gpwrdn_tmp;
0693 
0694     /* Switch-on voltage to the core */
0695     gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0696     gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
0697     dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0698     udelay(5);
0699 
0700     /* Reset core */
0701     gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0702     gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
0703     dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0704     udelay(5);
0705 
0706     /* Disable Power Down Clamp */
0707     gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0708     gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
0709     dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0710     udelay(5);
0711 
0712     /* Deassert reset core */
0713     gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0714     gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
0715     dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0716     udelay(5);
0717 
0718     /* Disable PMU interrupt */
0719     gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0720     gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
0721     dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0722 
0723     /* De-assert Wakeup Logic */
0724     gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0725     gpwrdn_tmp &= ~GPWRDN_PMUACTV;
0726     dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0727 
0728     hsotg->hibernated = 0;
0729     hsotg->bus_suspended = 0;
0730 
0731     if (gpwrdn & GPWRDN_IDSTS) {
0732         hsotg->op_state = OTG_STATE_B_PERIPHERAL;
0733         dwc2_core_init(hsotg, false);
0734         dwc2_enable_global_interrupts(hsotg);
0735         dwc2_hsotg_core_init_disconnected(hsotg, false);
0736         dwc2_hsotg_core_connect(hsotg);
0737     } else {
0738         hsotg->op_state = OTG_STATE_A_HOST;
0739 
0740         /* Initialize the Core for Host mode */
0741         dwc2_core_init(hsotg, false);
0742         dwc2_enable_global_interrupts(hsotg);
0743         dwc2_hcd_start(hsotg);
0744     }
0745 }
0746 
0747 /*
0748  * GPWRDN interrupt handler.
0749  *
0750  * The GPWRDN interrupts are those that occur in both Host and
0751  * Device mode while core is in hibernated state.
0752  */
0753 static int dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
0754 {
0755     u32 gpwrdn;
0756     int linestate;
0757     int ret = 0;
0758 
0759     gpwrdn = dwc2_readl(hsotg, GPWRDN);
0760     /* clear all interrupt */
0761     dwc2_writel(hsotg, gpwrdn, GPWRDN);
0762     linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
0763     dev_dbg(hsotg->dev,
0764         "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
0765         gpwrdn);
0766 
0767     if ((gpwrdn & GPWRDN_DISCONN_DET) &&
0768         (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
0769         dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
0770         /*
0771          * Call disconnect detect function to exit from
0772          * hibernation
0773          */
0774         dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
0775     } else if ((gpwrdn & GPWRDN_LNSTSCHG) &&
0776            (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
0777         dev_dbg(hsotg->dev, "%s: GPWRDN_LNSTSCHG\n", __func__);
0778         if (hsotg->hw_params.hibernation &&
0779             hsotg->hibernated) {
0780             if (gpwrdn & GPWRDN_IDSTS) {
0781                 ret = dwc2_exit_hibernation(hsotg, 0, 0, 0);
0782                 if (ret)
0783                     dev_err(hsotg->dev,
0784                         "exit hibernation failed.\n");
0785                 call_gadget(hsotg, resume);
0786             } else {
0787                 ret = dwc2_exit_hibernation(hsotg, 1, 0, 1);
0788                 if (ret)
0789                     dev_err(hsotg->dev,
0790                         "exit hibernation failed.\n");
0791             }
0792         }
0793     } else if ((gpwrdn & GPWRDN_RST_DET) &&
0794            (gpwrdn & GPWRDN_RST_DET_MSK)) {
0795         dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
0796         if (!linestate) {
0797             ret = dwc2_exit_hibernation(hsotg, 0, 1, 0);
0798             if (ret)
0799                 dev_err(hsotg->dev,
0800                     "exit hibernation failed.\n");
0801         }
0802     } else if ((gpwrdn & GPWRDN_STS_CHGINT) &&
0803            (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
0804         dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
0805         /*
0806          * As GPWRDN_STS_CHGINT exit from hibernation flow is
0807          * the same as in GPWRDN_DISCONN_DET flow. Call
0808          * disconnect detect helper function to exit from
0809          * hibernation.
0810          */
0811         dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
0812     }
0813 
0814     return ret;
0815 }
0816 
0817 /*
0818  * Common interrupt handler
0819  *
0820  * The common interrupts are those that occur in both Host and Device mode.
0821  * This handler handles the following interrupts:
0822  * - Mode Mismatch Interrupt
0823  * - OTG Interrupt
0824  * - Connector ID Status Change Interrupt
0825  * - Disconnect Interrupt
0826  * - Session Request Interrupt
0827  * - Resume / Remote Wakeup Detected Interrupt
0828  * - Suspend Interrupt
0829  */
0830 irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
0831 {
0832     struct dwc2_hsotg *hsotg = dev;
0833     u32 gintsts;
0834     irqreturn_t retval = IRQ_NONE;
0835 
0836     spin_lock(&hsotg->lock);
0837 
0838     if (!dwc2_is_controller_alive(hsotg)) {
0839         dev_warn(hsotg->dev, "Controller is dead\n");
0840         goto out;
0841     }
0842 
0843     /* Reading current frame number value in device or host modes. */
0844     if (dwc2_is_device_mode(hsotg))
0845         hsotg->frame_number = (dwc2_readl(hsotg, DSTS)
0846                        & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
0847     else
0848         hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
0849                        & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
0850 
0851     gintsts = dwc2_read_common_intr(hsotg);
0852     if (gintsts & ~GINTSTS_PRTINT)
0853         retval = IRQ_HANDLED;
0854 
0855     /* In case of hibernated state gintsts must not work */
0856     if (hsotg->hibernated) {
0857         dwc2_handle_gpwrdn_intr(hsotg);
0858         retval = IRQ_HANDLED;
0859         goto out;
0860     }
0861 
0862     if (gintsts & GINTSTS_MODEMIS)
0863         dwc2_handle_mode_mismatch_intr(hsotg);
0864     if (gintsts & GINTSTS_OTGINT)
0865         dwc2_handle_otg_intr(hsotg);
0866     if (gintsts & GINTSTS_CONIDSTSCHNG)
0867         dwc2_handle_conn_id_status_change_intr(hsotg);
0868     if (gintsts & GINTSTS_DISCONNINT)
0869         dwc2_handle_disconnect_intr(hsotg);
0870     if (gintsts & GINTSTS_SESSREQINT)
0871         dwc2_handle_session_req_intr(hsotg);
0872     if (gintsts & GINTSTS_WKUPINT)
0873         dwc2_handle_wakeup_detected_intr(hsotg);
0874     if (gintsts & GINTSTS_USBSUSP)
0875         dwc2_handle_usb_suspend_intr(hsotg);
0876     if (gintsts & GINTSTS_LPMTRANRCVD)
0877         dwc2_handle_lpm_intr(hsotg);
0878 
0879     if (gintsts & GINTSTS_PRTINT) {
0880         /*
0881          * The port interrupt occurs while in device mode with HPRT0
0882          * Port Enable/Disable
0883          */
0884         if (dwc2_is_device_mode(hsotg)) {
0885             dev_dbg(hsotg->dev,
0886                 " --Port interrupt received in Device mode--\n");
0887             dwc2_handle_usb_port_intr(hsotg);
0888             retval = IRQ_HANDLED;
0889         }
0890     }
0891 
0892 out:
0893     spin_unlock(&hsotg->lock);
0894     return retval;
0895 }