root/drivers/usb/dwc2/core_intr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dwc2_op_state_str
  2. dwc2_handle_usb_port_intr
  3. dwc2_handle_mode_mismatch_intr
  4. dwc2_handle_otg_intr
  5. dwc2_handle_conn_id_status_change_intr
  6. dwc2_handle_session_req_intr
  7. dwc2_wakeup_from_lpm_l1
  8. dwc2_handle_wakeup_detected_intr
  9. dwc2_handle_disconnect_intr
  10. dwc2_handle_usb_suspend_intr
  11. dwc2_handle_lpm_intr
  12. dwc2_read_common_intr
  13. dwc2_handle_gpwrdn_intr
  14. dwc2_handle_common_intr

   1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2 /*
   3  * core_intr.c - DesignWare HS OTG Controller common interrupt handling
   4  *
   5  * Copyright (C) 2004-2013 Synopsys, Inc.
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions, and the following disclaimer,
  12  *    without modification.
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  * 3. The names of the above-listed copyright holders may not be used
  17  *    to endorse or promote products derived from this software without
  18  *    specific prior written permission.
  19  *
  20  * ALTERNATIVELY, this software may be distributed under the terms of the
  21  * GNU General Public License ("GPL") as published by the Free Software
  22  * Foundation; either version 2 of the License, or (at your option) any
  23  * later version.
  24  *
  25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  26  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  27  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36  */
  37 
  38 /*
  39  * This file contains the common interrupt handlers
  40  */
  41 #include <linux/kernel.h>
  42 #include <linux/module.h>
  43 #include <linux/moduleparam.h>
  44 #include <linux/spinlock.h>
  45 #include <linux/interrupt.h>
  46 #include <linux/dma-mapping.h>
  47 #include <linux/io.h>
  48 #include <linux/slab.h>
  49 #include <linux/usb.h>
  50 
  51 #include <linux/usb/hcd.h>
  52 #include <linux/usb/ch11.h>
  53 
  54 #include "core.h"
  55 #include "hcd.h"
  56 
  57 static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
  58 {
  59         switch (hsotg->op_state) {
  60         case OTG_STATE_A_HOST:
  61                 return "a_host";
  62         case OTG_STATE_A_SUSPEND:
  63                 return "a_suspend";
  64         case OTG_STATE_A_PERIPHERAL:
  65                 return "a_peripheral";
  66         case OTG_STATE_B_PERIPHERAL:
  67                 return "b_peripheral";
  68         case OTG_STATE_B_HOST:
  69                 return "b_host";
  70         default:
  71                 return "unknown";
  72         }
  73 }
  74 
  75 /**
  76  * dwc2_handle_usb_port_intr - handles OTG PRTINT interrupts.
  77  * When the PRTINT interrupt fires, there are certain status bits in the Host
  78  * Port that needs to get cleared.
  79  *
  80  * @hsotg: Programming view of DWC_otg controller
  81  */
  82 static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
  83 {
  84         u32 hprt0 = dwc2_readl(hsotg, HPRT0);
  85 
  86         if (hprt0 & HPRT0_ENACHG) {
  87                 hprt0 &= ~HPRT0_ENA;
  88                 dwc2_writel(hsotg, hprt0, HPRT0);
  89         }
  90 }
  91 
  92 /**
  93  * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
  94  *
  95  * @hsotg: Programming view of DWC_otg controller
  96  */
  97 static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
  98 {
  99         /* Clear interrupt */
 100         dwc2_writel(hsotg, GINTSTS_MODEMIS, GINTSTS);
 101 
 102         dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
 103                  dwc2_is_host_mode(hsotg) ? "Host" : "Device");
 104 }
 105 
 106 /**
 107  * dwc2_handle_otg_intr() - Handles the OTG Interrupts. It reads the OTG
 108  * Interrupt Register (GOTGINT) to determine what interrupt has occurred.
 109  *
 110  * @hsotg: Programming view of DWC_otg controller
 111  */
 112 static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
 113 {
 114         u32 gotgint;
 115         u32 gotgctl;
 116         u32 gintmsk;
 117 
 118         gotgint = dwc2_readl(hsotg, GOTGINT);
 119         gotgctl = dwc2_readl(hsotg, GOTGCTL);
 120         dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
 121                 dwc2_op_state_str(hsotg));
 122 
 123         if (gotgint & GOTGINT_SES_END_DET) {
 124                 dev_dbg(hsotg->dev,
 125                         " ++OTG Interrupt: Session End Detected++ (%s)\n",
 126                         dwc2_op_state_str(hsotg));
 127                 gotgctl = dwc2_readl(hsotg, GOTGCTL);
 128 
 129                 if (dwc2_is_device_mode(hsotg))
 130                         dwc2_hsotg_disconnect(hsotg);
 131 
 132                 if (hsotg->op_state == OTG_STATE_B_HOST) {
 133                         hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 134                 } else {
 135                         /*
 136                          * If not B_HOST and Device HNP still set, HNP did
 137                          * not succeed!
 138                          */
 139                         if (gotgctl & GOTGCTL_DEVHNPEN) {
 140                                 dev_dbg(hsotg->dev, "Session End Detected\n");
 141                                 dev_err(hsotg->dev,
 142                                         "Device Not Connected/Responding!\n");
 143                         }
 144 
 145                         /*
 146                          * If Session End Detected the B-Cable has been
 147                          * disconnected
 148                          */
 149                         /* Reset to a clean state */
 150                         hsotg->lx_state = DWC2_L0;
 151                 }
 152 
 153                 gotgctl = dwc2_readl(hsotg, GOTGCTL);
 154                 gotgctl &= ~GOTGCTL_DEVHNPEN;
 155                 dwc2_writel(hsotg, gotgctl, GOTGCTL);
 156         }
 157 
 158         if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
 159                 dev_dbg(hsotg->dev,
 160                         " ++OTG Interrupt: Session Request Success Status Change++\n");
 161                 gotgctl = dwc2_readl(hsotg, GOTGCTL);
 162                 if (gotgctl & GOTGCTL_SESREQSCS) {
 163                         if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
 164                             hsotg->params.i2c_enable) {
 165                                 hsotg->srp_success = 1;
 166                         } else {
 167                                 /* Clear Session Request */
 168                                 gotgctl = dwc2_readl(hsotg, GOTGCTL);
 169                                 gotgctl &= ~GOTGCTL_SESREQ;
 170                                 dwc2_writel(hsotg, gotgctl, GOTGCTL);
 171                         }
 172                 }
 173         }
 174 
 175         if (gotgint & GOTGINT_HST_NEG_SUC_STS_CHNG) {
 176                 /*
 177                  * Print statements during the HNP interrupt handling
 178                  * can cause it to fail
 179                  */
 180                 gotgctl = dwc2_readl(hsotg, GOTGCTL);
 181                 /*
 182                  * WA for 3.00a- HW is not setting cur_mode, even sometimes
 183                  * this does not help
 184                  */
 185                 if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)
 186                         udelay(100);
 187                 if (gotgctl & GOTGCTL_HSTNEGSCS) {
 188                         if (dwc2_is_host_mode(hsotg)) {
 189                                 hsotg->op_state = OTG_STATE_B_HOST;
 190                                 /*
 191                                  * Need to disable SOF interrupt immediately.
 192                                  * When switching from device to host, the PCD
 193                                  * interrupt handler won't handle the interrupt
 194                                  * if host mode is already set. The HCD
 195                                  * interrupt handler won't get called if the
 196                                  * HCD state is HALT. This means that the
 197                                  * interrupt does not get handled and Linux
 198                                  * complains loudly.
 199                                  */
 200                                 gintmsk = dwc2_readl(hsotg, GINTMSK);
 201                                 gintmsk &= ~GINTSTS_SOF;
 202                                 dwc2_writel(hsotg, gintmsk, GINTMSK);
 203 
 204                                 /*
 205                                  * Call callback function with spin lock
 206                                  * released
 207                                  */
 208                                 spin_unlock(&hsotg->lock);
 209 
 210                                 /* Initialize the Core for Host mode */
 211                                 dwc2_hcd_start(hsotg);
 212                                 spin_lock(&hsotg->lock);
 213                                 hsotg->op_state = OTG_STATE_B_HOST;
 214                         }
 215                 } else {
 216                         gotgctl = dwc2_readl(hsotg, GOTGCTL);
 217                         gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
 218                         dwc2_writel(hsotg, gotgctl, GOTGCTL);
 219                         dev_dbg(hsotg->dev, "HNP Failed\n");
 220                         dev_err(hsotg->dev,
 221                                 "Device Not Connected/Responding\n");
 222                 }
 223         }
 224 
 225         if (gotgint & GOTGINT_HST_NEG_DET) {
 226                 /*
 227                  * The disconnect interrupt is set at the same time as
 228                  * Host Negotiation Detected. During the mode switch all
 229                  * interrupts are cleared so the disconnect interrupt
 230                  * handler will not get executed.
 231                  */
 232                 dev_dbg(hsotg->dev,
 233                         " ++OTG Interrupt: Host Negotiation Detected++ (%s)\n",
 234                         (dwc2_is_host_mode(hsotg) ? "Host" : "Device"));
 235                 if (dwc2_is_device_mode(hsotg)) {
 236                         dev_dbg(hsotg->dev, "a_suspend->a_peripheral (%d)\n",
 237                                 hsotg->op_state);
 238                         spin_unlock(&hsotg->lock);
 239                         dwc2_hcd_disconnect(hsotg, false);
 240                         spin_lock(&hsotg->lock);
 241                         hsotg->op_state = OTG_STATE_A_PERIPHERAL;
 242                 } else {
 243                         /* Need to disable SOF interrupt immediately */
 244                         gintmsk = dwc2_readl(hsotg, GINTMSK);
 245                         gintmsk &= ~GINTSTS_SOF;
 246                         dwc2_writel(hsotg, gintmsk, GINTMSK);
 247                         spin_unlock(&hsotg->lock);
 248                         dwc2_hcd_start(hsotg);
 249                         spin_lock(&hsotg->lock);
 250                         hsotg->op_state = OTG_STATE_A_HOST;
 251                 }
 252         }
 253 
 254         if (gotgint & GOTGINT_A_DEV_TOUT_CHG)
 255                 dev_dbg(hsotg->dev,
 256                         " ++OTG Interrupt: A-Device Timeout Change++\n");
 257         if (gotgint & GOTGINT_DBNCE_DONE)
 258                 dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
 259 
 260         /* Clear GOTGINT */
 261         dwc2_writel(hsotg, gotgint, GOTGINT);
 262 }
 263 
 264 /**
 265  * dwc2_handle_conn_id_status_change_intr() - Handles the Connector ID Status
 266  * Change Interrupt
 267  *
 268  * @hsotg: Programming view of DWC_otg controller
 269  *
 270  * Reads the OTG Interrupt Register (GOTCTL) to determine whether this is a
 271  * Device to Host Mode transition or a Host to Device Mode transition. This only
 272  * occurs when the cable is connected/removed from the PHY connector.
 273  */
 274 static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
 275 {
 276         u32 gintmsk;
 277 
 278         /* Clear interrupt */
 279         dwc2_writel(hsotg, GINTSTS_CONIDSTSCHNG, GINTSTS);
 280 
 281         /* Need to disable SOF interrupt immediately */
 282         gintmsk = dwc2_readl(hsotg, GINTMSK);
 283         gintmsk &= ~GINTSTS_SOF;
 284         dwc2_writel(hsotg, gintmsk, GINTMSK);
 285 
 286         dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
 287                 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
 288 
 289         /*
 290          * Need to schedule a work, as there are possible DELAY function calls.
 291          * Release lock before scheduling workq as it holds spinlock during
 292          * scheduling.
 293          */
 294         if (hsotg->wq_otg) {
 295                 spin_unlock(&hsotg->lock);
 296                 queue_work(hsotg->wq_otg, &hsotg->wf_otg);
 297                 spin_lock(&hsotg->lock);
 298         }
 299 }
 300 
 301 /**
 302  * dwc2_handle_session_req_intr() - This interrupt indicates that a device is
 303  * initiating the Session Request Protocol to request the host to turn on bus
 304  * power so a new session can begin
 305  *
 306  * @hsotg: Programming view of DWC_otg controller
 307  *
 308  * This handler responds by turning on bus power. If the DWC_otg controller is
 309  * in low power mode, this handler brings the controller out of low power mode
 310  * before turning on bus power.
 311  */
 312 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 313 {
 314         int ret;
 315 
 316         /* Clear interrupt */
 317         dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
 318 
 319         dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
 320                 hsotg->lx_state);
 321 
 322         if (dwc2_is_device_mode(hsotg)) {
 323                 if (hsotg->lx_state == DWC2_L2) {
 324                         ret = dwc2_exit_partial_power_down(hsotg, true);
 325                         if (ret && (ret != -ENOTSUPP))
 326                                 dev_err(hsotg->dev,
 327                                         "exit power_down failed\n");
 328                 }
 329 
 330                 /*
 331                  * Report disconnect if there is any previous session
 332                  * established
 333                  */
 334                 dwc2_hsotg_disconnect(hsotg);
 335         }
 336 }
 337 
 338 /**
 339  * dwc2_wakeup_from_lpm_l1 - Exit the device from LPM L1 state
 340  *
 341  * @hsotg: Programming view of DWC_otg controller
 342  *
 343  */
 344 static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
 345 {
 346         u32 glpmcfg;
 347         u32 i = 0;
 348 
 349         if (hsotg->lx_state != DWC2_L1) {
 350                 dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
 351                 return;
 352         }
 353 
 354         glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 355         if (dwc2_is_device_mode(hsotg)) {
 356                 dev_dbg(hsotg->dev, "Exit from L1 state\n");
 357                 glpmcfg &= ~GLPMCFG_ENBLSLPM;
 358                 glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
 359                 dwc2_writel(hsotg, glpmcfg, GLPMCFG);
 360 
 361                 do {
 362                         glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 363 
 364                         if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
 365                                          GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
 366                                 break;
 367 
 368                         udelay(1);
 369                 } while (++i < 200);
 370 
 371                 if (i == 200) {
 372                         dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
 373                         return;
 374                 }
 375                 dwc2_gadget_init_lpm(hsotg);
 376         } else {
 377                 /* TODO */
 378                 dev_err(hsotg->dev, "Host side LPM is not supported.\n");
 379                 return;
 380         }
 381 
 382         /* Change to L0 state */
 383         hsotg->lx_state = DWC2_L0;
 384 
 385         /* Inform gadget to exit from L1 */
 386         call_gadget(hsotg, resume);
 387 }
 388 
 389 /*
 390  * This interrupt indicates that the DWC_otg controller has detected a
 391  * resume or remote wakeup sequence. If the DWC_otg controller is in
 392  * low power mode, the handler must brings the controller out of low
 393  * power mode. The controller automatically begins resume signaling.
 394  * The handler schedules a time to stop resume signaling.
 395  */
 396 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 397 {
 398         int ret;
 399 
 400         /* Clear interrupt */
 401         dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
 402 
 403         dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
 404         dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
 405 
 406         if (hsotg->lx_state == DWC2_L1) {
 407                 dwc2_wakeup_from_lpm_l1(hsotg);
 408                 return;
 409         }
 410 
 411         if (dwc2_is_device_mode(hsotg)) {
 412                 dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
 413                         dwc2_readl(hsotg, DSTS));
 414                 if (hsotg->lx_state == DWC2_L2) {
 415                         u32 dctl = dwc2_readl(hsotg, DCTL);
 416 
 417                         /* Clear Remote Wakeup Signaling */
 418                         dctl &= ~DCTL_RMTWKUPSIG;
 419                         dwc2_writel(hsotg, dctl, DCTL);
 420                         ret = dwc2_exit_partial_power_down(hsotg, true);
 421                         if (ret && (ret != -ENOTSUPP))
 422                                 dev_err(hsotg->dev, "exit power_down failed\n");
 423 
 424                         call_gadget(hsotg, resume);
 425                 }
 426                 /* Change to L0 state */
 427                 hsotg->lx_state = DWC2_L0;
 428         } else {
 429                 if (hsotg->params.power_down)
 430                         return;
 431 
 432                 if (hsotg->lx_state != DWC2_L1) {
 433                         u32 pcgcctl = dwc2_readl(hsotg, PCGCTL);
 434 
 435                         /* Restart the Phy Clock */
 436                         pcgcctl &= ~PCGCTL_STOPPCLK;
 437                         dwc2_writel(hsotg, pcgcctl, PCGCTL);
 438 
 439                         /*
 440                          * If we've got this quirk then the PHY is stuck upon
 441                          * wakeup.  Assert reset.  This will propagate out and
 442                          * eventually we'll re-enumerate the device.  Not great
 443                          * but the best we can do.  We can't call phy_reset()
 444                          * at interrupt time but there's no hurry, so we'll
 445                          * schedule it for later.
 446                          */
 447                         if (hsotg->reset_phy_on_wake)
 448                                 dwc2_host_schedule_phy_reset(hsotg);
 449 
 450                         mod_timer(&hsotg->wkp_timer,
 451                                   jiffies + msecs_to_jiffies(71));
 452                 } else {
 453                         /* Change to L0 state */
 454                         hsotg->lx_state = DWC2_L0;
 455                 }
 456         }
 457 }
 458 
 459 /*
 460  * This interrupt indicates that a device has been disconnected from the
 461  * root port
 462  */
 463 static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
 464 {
 465         dwc2_writel(hsotg, GINTSTS_DISCONNINT, GINTSTS);
 466 
 467         dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
 468                 dwc2_is_host_mode(hsotg) ? "Host" : "Device",
 469                 dwc2_op_state_str(hsotg));
 470 
 471         if (hsotg->op_state == OTG_STATE_A_HOST)
 472                 dwc2_hcd_disconnect(hsotg, false);
 473 }
 474 
 475 /*
 476  * This interrupt indicates that SUSPEND state has been detected on the USB.
 477  *
 478  * For HNP the USB Suspend interrupt signals the change from "a_peripheral"
 479  * to "a_host".
 480  *
 481  * When power management is enabled the core will be put in low power mode.
 482  */
 483 static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 484 {
 485         u32 dsts;
 486         int ret;
 487 
 488         /* Clear interrupt */
 489         dwc2_writel(hsotg, GINTSTS_USBSUSP, GINTSTS);
 490 
 491         dev_dbg(hsotg->dev, "USB SUSPEND\n");
 492 
 493         if (dwc2_is_device_mode(hsotg)) {
 494                 /*
 495                  * Check the Device status register to determine if the Suspend
 496                  * state is active
 497                  */
 498                 dsts = dwc2_readl(hsotg, DSTS);
 499                 dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
 500                 dev_dbg(hsotg->dev,
 501                         "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d HWCFG4.Hibernation=%d\n",
 502                         !!(dsts & DSTS_SUSPSTS),
 503                         hsotg->hw_params.power_optimized,
 504                         hsotg->hw_params.hibernation);
 505 
 506                 /* Ignore suspend request before enumeration */
 507                 if (!dwc2_is_device_connected(hsotg)) {
 508                         dev_dbg(hsotg->dev,
 509                                 "ignore suspend request before enumeration\n");
 510                         return;
 511                 }
 512                 if (dsts & DSTS_SUSPSTS) {
 513                         if (hsotg->hw_params.power_optimized) {
 514                                 ret = dwc2_enter_partial_power_down(hsotg);
 515                                 if (ret) {
 516                                         if (ret != -ENOTSUPP)
 517                                                 dev_err(hsotg->dev,
 518                                                         "%s: enter partial_power_down failed\n",
 519                                                         __func__);
 520                                         goto skip_power_saving;
 521                                 }
 522 
 523                                 udelay(100);
 524 
 525                                 /* Ask phy to be suspended */
 526                                 if (!IS_ERR_OR_NULL(hsotg->uphy))
 527                                         usb_phy_set_suspend(hsotg->uphy, true);
 528                         }
 529 
 530                         if (hsotg->hw_params.hibernation) {
 531                                 ret = dwc2_enter_hibernation(hsotg, 0);
 532                                 if (ret && ret != -ENOTSUPP)
 533                                         dev_err(hsotg->dev,
 534                                                 "%s: enter hibernation failed\n",
 535                                                 __func__);
 536                         }
 537 skip_power_saving:
 538                         /*
 539                          * Change to L2 (suspend) state before releasing
 540                          * spinlock
 541                          */
 542                         hsotg->lx_state = DWC2_L2;
 543 
 544                         /* Call gadget suspend callback */
 545                         call_gadget(hsotg, suspend);
 546                 }
 547         } else {
 548                 if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
 549                         dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
 550 
 551                         /* Change to L2 (suspend) state */
 552                         hsotg->lx_state = DWC2_L2;
 553                         /* Clear the a_peripheral flag, back to a_host */
 554                         spin_unlock(&hsotg->lock);
 555                         dwc2_hcd_start(hsotg);
 556                         spin_lock(&hsotg->lock);
 557                         hsotg->op_state = OTG_STATE_A_HOST;
 558                 }
 559         }
 560 }
 561 
 562 /**
 563  * dwc2_handle_lpm_intr - GINTSTS_LPMTRANRCVD Interrupt handler
 564  *
 565  * @hsotg: Programming view of DWC_otg controller
 566  *
 567  */
 568 static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
 569 {
 570         u32 glpmcfg;
 571         u32 pcgcctl;
 572         u32 hird;
 573         u32 hird_thres;
 574         u32 hird_thres_en;
 575         u32 enslpm;
 576 
 577         /* Clear interrupt */
 578         dwc2_writel(hsotg, GINTSTS_LPMTRANRCVD, GINTSTS);
 579 
 580         glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 581 
 582         if (!(glpmcfg & GLPMCFG_LPMCAP)) {
 583                 dev_err(hsotg->dev, "Unexpected LPM interrupt\n");
 584                 return;
 585         }
 586 
 587         hird = (glpmcfg & GLPMCFG_HIRD_MASK) >> GLPMCFG_HIRD_SHIFT;
 588         hird_thres = (glpmcfg & GLPMCFG_HIRD_THRES_MASK &
 589                         ~GLPMCFG_HIRD_THRES_EN) >> GLPMCFG_HIRD_THRES_SHIFT;
 590         hird_thres_en = glpmcfg & GLPMCFG_HIRD_THRES_EN;
 591         enslpm = glpmcfg & GLPMCFG_ENBLSLPM;
 592 
 593         if (dwc2_is_device_mode(hsotg)) {
 594                 dev_dbg(hsotg->dev, "HIRD_THRES_EN = %d\n", hird_thres_en);
 595 
 596                 if (hird_thres_en && hird >= hird_thres) {
 597                         dev_dbg(hsotg->dev, "L1 with utmi_l1_suspend_n\n");
 598                 } else if (enslpm) {
 599                         dev_dbg(hsotg->dev, "L1 with utmi_sleep_n\n");
 600                 } else {
 601                         dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n");
 602 
 603                         pcgcctl = dwc2_readl(hsotg, PCGCTL);
 604                         pcgcctl |= PCGCTL_ENBL_SLEEP_GATING;
 605                         dwc2_writel(hsotg, pcgcctl, PCGCTL);
 606                 }
 607                 /**
 608                  * Examine prt_sleep_sts after TL1TokenTetry period max (10 us)
 609                  */
 610                 udelay(10);
 611 
 612                 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 613 
 614                 if (glpmcfg & GLPMCFG_SLPSTS) {
 615                         /* Save the current state */
 616                         hsotg->lx_state = DWC2_L1;
 617                         dev_dbg(hsotg->dev,
 618                                 "Core is in L1 sleep glpmcfg=%08x\n", glpmcfg);
 619 
 620                         /* Inform gadget that we are in L1 state */
 621                         call_gadget(hsotg, suspend);
 622                 }
 623         }
 624 }
 625 
 626 #define GINTMSK_COMMON  (GINTSTS_WKUPINT | GINTSTS_SESSREQINT |         \
 627                          GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT |        \
 628                          GINTSTS_MODEMIS | GINTSTS_DISCONNINT |         \
 629                          GINTSTS_USBSUSP | GINTSTS_PRTINT |             \
 630                          GINTSTS_LPMTRANRCVD)
 631 
 632 /*
 633  * This function returns the Core Interrupt register
 634  */
 635 static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
 636 {
 637         u32 gintsts;
 638         u32 gintmsk;
 639         u32 gahbcfg;
 640         u32 gintmsk_common = GINTMSK_COMMON;
 641 
 642         gintsts = dwc2_readl(hsotg, GINTSTS);
 643         gintmsk = dwc2_readl(hsotg, GINTMSK);
 644         gahbcfg = dwc2_readl(hsotg, GAHBCFG);
 645 
 646         /* If any common interrupts set */
 647         if (gintsts & gintmsk_common)
 648                 dev_dbg(hsotg->dev, "gintsts=%08x  gintmsk=%08x\n",
 649                         gintsts, gintmsk);
 650 
 651         if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
 652                 return gintsts & gintmsk & gintmsk_common;
 653         else
 654                 return 0;
 655 }
 656 
 657 /*
 658  * GPWRDN interrupt handler.
 659  *
 660  * The GPWRDN interrupts are those that occur in both Host and
 661  * Device mode while core is in hibernated state.
 662  */
 663 static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 664 {
 665         u32 gpwrdn;
 666         int linestate;
 667 
 668         gpwrdn = dwc2_readl(hsotg, GPWRDN);
 669         /* clear all interrupt */
 670         dwc2_writel(hsotg, gpwrdn, GPWRDN);
 671         linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
 672         dev_dbg(hsotg->dev,
 673                 "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
 674                 gpwrdn);
 675 
 676         if ((gpwrdn & GPWRDN_DISCONN_DET) &&
 677             (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
 678                 u32 gpwrdn_tmp;
 679 
 680                 dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
 681 
 682                 /* Switch-on voltage to the core */
 683                 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
 684                 gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
 685                 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 686                 udelay(10);
 687 
 688                 /* Reset core */
 689                 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
 690                 gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
 691                 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 692                 udelay(10);
 693 
 694                 /* Disable Power Down Clamp */
 695                 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
 696                 gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
 697                 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 698                 udelay(10);
 699 
 700                 /* Deassert reset core */
 701                 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
 702                 gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
 703                 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 704                 udelay(10);
 705 
 706                 /* Disable PMU interrupt */
 707                 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
 708                 gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
 709                 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 710 
 711                 /* De-assert Wakeup Logic */
 712                 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
 713                 gpwrdn_tmp &= ~GPWRDN_PMUACTV;
 714                 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 715 
 716                 hsotg->hibernated = 0;
 717 
 718                 if (gpwrdn & GPWRDN_IDSTS) {
 719                         hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 720                         dwc2_core_init(hsotg, false);
 721                         dwc2_enable_global_interrupts(hsotg);
 722                         dwc2_hsotg_core_init_disconnected(hsotg, false);
 723                         dwc2_hsotg_core_connect(hsotg);
 724                 } else {
 725                         hsotg->op_state = OTG_STATE_A_HOST;
 726 
 727                         /* Initialize the Core for Host mode */
 728                         dwc2_core_init(hsotg, false);
 729                         dwc2_enable_global_interrupts(hsotg);
 730                         dwc2_hcd_start(hsotg);
 731                 }
 732         }
 733 
 734         if ((gpwrdn & GPWRDN_LNSTSCHG) &&
 735             (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
 736                 dev_dbg(hsotg->dev, "%s: GPWRDN_LNSTSCHG\n", __func__);
 737                 if (hsotg->hw_params.hibernation &&
 738                     hsotg->hibernated) {
 739                         if (gpwrdn & GPWRDN_IDSTS) {
 740                                 dwc2_exit_hibernation(hsotg, 0, 0, 0);
 741                                 call_gadget(hsotg, resume);
 742                         } else {
 743                                 dwc2_exit_hibernation(hsotg, 1, 0, 1);
 744                         }
 745                 }
 746         }
 747         if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) {
 748                 dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
 749                 if (!linestate && (gpwrdn & GPWRDN_BSESSVLD))
 750                         dwc2_exit_hibernation(hsotg, 0, 1, 0);
 751         }
 752         if ((gpwrdn & GPWRDN_STS_CHGINT) &&
 753             (gpwrdn & GPWRDN_STS_CHGINT_MSK) && linestate) {
 754                 dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
 755                 if (hsotg->hw_params.hibernation &&
 756                     hsotg->hibernated) {
 757                         if (gpwrdn & GPWRDN_IDSTS) {
 758                                 dwc2_exit_hibernation(hsotg, 0, 0, 0);
 759                                 call_gadget(hsotg, resume);
 760                         } else {
 761                                 dwc2_exit_hibernation(hsotg, 1, 0, 1);
 762                         }
 763                 }
 764         }
 765 }
 766 
 767 /*
 768  * Common interrupt handler
 769  *
 770  * The common interrupts are those that occur in both Host and Device mode.
 771  * This handler handles the following interrupts:
 772  * - Mode Mismatch Interrupt
 773  * - OTG Interrupt
 774  * - Connector ID Status Change Interrupt
 775  * - Disconnect Interrupt
 776  * - Session Request Interrupt
 777  * - Resume / Remote Wakeup Detected Interrupt
 778  * - Suspend Interrupt
 779  */
 780 irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 781 {
 782         struct dwc2_hsotg *hsotg = dev;
 783         u32 gintsts;
 784         irqreturn_t retval = IRQ_NONE;
 785 
 786         spin_lock(&hsotg->lock);
 787 
 788         if (!dwc2_is_controller_alive(hsotg)) {
 789                 dev_warn(hsotg->dev, "Controller is dead\n");
 790                 goto out;
 791         }
 792 
 793         /* Reading current frame number value in device or host modes. */
 794         if (dwc2_is_device_mode(hsotg))
 795                 hsotg->frame_number = (dwc2_readl(hsotg, DSTS)
 796                                        & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
 797         else
 798                 hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
 799                                        & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
 800 
 801         gintsts = dwc2_read_common_intr(hsotg);
 802         if (gintsts & ~GINTSTS_PRTINT)
 803                 retval = IRQ_HANDLED;
 804 
 805         /* In case of hibernated state gintsts must not work */
 806         if (hsotg->hibernated) {
 807                 dwc2_handle_gpwrdn_intr(hsotg);
 808                 retval = IRQ_HANDLED;
 809                 goto out;
 810         }
 811 
 812         if (gintsts & GINTSTS_MODEMIS)
 813                 dwc2_handle_mode_mismatch_intr(hsotg);
 814         if (gintsts & GINTSTS_OTGINT)
 815                 dwc2_handle_otg_intr(hsotg);
 816         if (gintsts & GINTSTS_CONIDSTSCHNG)
 817                 dwc2_handle_conn_id_status_change_intr(hsotg);
 818         if (gintsts & GINTSTS_DISCONNINT)
 819                 dwc2_handle_disconnect_intr(hsotg);
 820         if (gintsts & GINTSTS_SESSREQINT)
 821                 dwc2_handle_session_req_intr(hsotg);
 822         if (gintsts & GINTSTS_WKUPINT)
 823                 dwc2_handle_wakeup_detected_intr(hsotg);
 824         if (gintsts & GINTSTS_USBSUSP)
 825                 dwc2_handle_usb_suspend_intr(hsotg);
 826         if (gintsts & GINTSTS_LPMTRANRCVD)
 827                 dwc2_handle_lpm_intr(hsotg);
 828 
 829         if (gintsts & GINTSTS_PRTINT) {
 830                 /*
 831                  * The port interrupt occurs while in device mode with HPRT0
 832                  * Port Enable/Disable
 833                  */
 834                 if (dwc2_is_device_mode(hsotg)) {
 835                         dev_dbg(hsotg->dev,
 836                                 " --Port interrupt received in Device mode--\n");
 837                         dwc2_handle_usb_port_intr(hsotg);
 838                         retval = IRQ_HANDLED;
 839                 }
 840         }
 841 
 842 out:
 843         spin_unlock(&hsotg->lock);
 844         return retval;
 845 }

/* [<][>][^][v][top][bottom][index][help] */