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