Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

dwc_otg_cil_intr.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
00003  * $Revision: #31 $
00004  * $Date: 2011/10/24 $
00005  * $Change: 1871286 $
00006  *
00007  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
00008  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
00009  * otherwise expressly agreed to in writing between Synopsys and you.
00010  *
00011  * The Software IS NOT an item of Licensed Software or Licensed Product under
00012  * any End User Software License Agreement or Agreement for Licensed Product
00013  * with Synopsys or any supplement thereto. You are permitted to use and
00014  * redistribute this Software in source and binary forms, with or without
00015  * modification, provided that redistributions of source code must retain this
00016  * notice. You may not view, use, disclose, copy or distribute this file or
00017  * any information contained herein except pursuant to this license grant from
00018  * Synopsys. If you do not agree with this notice, including the disclaimer
00019  * below, then you are not authorized to use the Software.
00020  *
00021  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
00022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
00025  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00027  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00031  * DAMAGE.
00032  * ========================================================================== */
00033 
00042 #include "dwc_os.h"
00043 #include "dwc_otg_regs.h"
00044 #include "dwc_otg_cil.h"
00045 #include "dwc_otg_driver.h"
00046 #include "dwc_otg_pcd.h"
00047 #include "dwc_otg_hcd.h"
00048 
00049 #ifdef DEBUG
00050 inline const char *op_state_str(dwc_otg_core_if_t * core_if)
00051 {
00052         return (core_if->op_state == A_HOST ? "a_host" :
00053                 (core_if->op_state == A_SUSPEND ? "a_suspend" :
00054                  (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
00055                   (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
00056                    (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
00057 }
00058 #endif
00059 
00064 int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
00065 {
00066         gintsts_data_t gintsts;
00067         DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
00068                  dwc_otg_mode(core_if) ? "Host" : "Device");
00069 
00070         /* Clear interrupt */
00071         gintsts.d32 = 0;
00072         gintsts.b.modemismatch = 1;
00073         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
00074         return 1;
00075 }
00076 
00084 int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
00085 {
00086         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
00087         gotgint_data_t gotgint;
00088         gotgctl_data_t gotgctl;
00089         gintmsk_data_t gintmsk;
00090         gpwrdn_data_t gpwrdn;
00091 
00092         gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
00093         gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
00094         DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
00095                     op_state_str(core_if));
00096 
00097         if (gotgint.b.sesenddet) {
00098                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
00099                             "Session End Detected++ (%s)\n",
00100                             op_state_str(core_if));
00101                 gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
00102 
00103                 if (core_if->op_state == B_HOST) {
00104                         cil_pcd_start(core_if);
00105                         core_if->op_state = B_PERIPHERAL;
00106                 } else {
00107                         /* If not B_HOST and Device HNP still set. HNP
00108                          * Did not succeed!*/
00109                         if (gotgctl.b.devhnpen) {
00110                                 DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
00111                                 __DWC_ERROR("Device Not Connected/Responding!\n");
00112                         }
00113 
00114                         /* If Session End Detected the B-Cable has
00115                          * been disconnected. */
00116                         /* Reset PCD and Gadget driver to a
00117                          * clean state. */
00118                         core_if->lx_state = DWC_OTG_L0;
00119                         DWC_SPINUNLOCK(core_if->lock);
00120                         cil_pcd_stop(core_if);
00121                         DWC_SPINLOCK(core_if->lock);
00122 
00123                         if (core_if->adp_enable) {
00124                                 if (core_if->power_down == 2) {
00125                                         gpwrdn.d32 = 0;
00126                                         gpwrdn.b.pwrdnswtch = 1;
00127                                         DWC_MODIFY_REG32(&core_if->
00128                                                          core_global_regs->
00129                                                          gpwrdn, gpwrdn.d32, 0);
00130                                 }
00131 
00132                                 gpwrdn.d32 = 0;
00133                                 gpwrdn.b.pmuintsel = 1;
00134                                 gpwrdn.b.pmuactv = 1;
00135                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00136                                                  gpwrdn, 0, gpwrdn.d32);
00137 
00138                                 dwc_otg_adp_sense_start(core_if);
00139                         }
00140                 }
00141 
00142                 gotgctl.d32 = 0;
00143                 gotgctl.b.devhnpen = 1;
00144                 DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
00145         }
00146         if (gotgint.b.sesreqsucstschng) {
00147                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
00148                             "Session Reqeust Success Status Change++\n");
00149                 gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
00150                 if (gotgctl.b.sesreqscs) {
00151 
00152                         if ((core_if->core_params->phy_type ==
00153                              DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
00154                                 core_if->srp_success = 1;
00155                         } else {
00156                                 DWC_SPINUNLOCK(core_if->lock);
00157                                 cil_pcd_resume(core_if);
00158                                 DWC_SPINLOCK(core_if->lock);
00159                                 /* Clear Session Request */
00160                                 gotgctl.d32 = 0;
00161                                 gotgctl.b.sesreq = 1;
00162                                 DWC_MODIFY_REG32(&global_regs->gotgctl,
00163                                                  gotgctl.d32, 0);
00164                         }
00165                 }
00166         }
00167         if (gotgint.b.hstnegsucstschng) {
00168                 /* Print statements during the HNP interrupt handling
00169                  * can cause it to fail.*/
00170                 gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
00171                 if (gotgctl.b.hstnegscs) {
00172                         if (dwc_otg_is_host_mode(core_if)) {
00173                                 core_if->op_state = B_HOST;
00174                                 /*
00175                                  * Need to disable SOF interrupt immediately.
00176                                  * When switching from device to host, the PCD
00177                                  * interrupt handler won't handle the
00178                                  * interrupt if host mode is already set. The
00179                                  * HCD interrupt handler won't get called if
00180                                  * the HCD state is HALT. This means that the
00181                                  * interrupt does not get handled and Linux
00182                                  * complains loudly.
00183                                  */
00184                                 gintmsk.d32 = 0;
00185                                 gintmsk.b.sofintr = 1;
00186                                 DWC_MODIFY_REG32(&global_regs->gintmsk,
00187                                                  gintmsk.d32, 0);
00188                                 /* Call callback function with spin lock released */
00189                                 DWC_SPINUNLOCK(core_if->lock);
00190                                 cil_pcd_stop(core_if);
00191                                 /*
00192                                  * Initialize the Core for Host mode.
00193                                  */
00194                                 cil_hcd_start(core_if);
00195                                 DWC_SPINLOCK(core_if->lock);
00196                                 core_if->op_state = B_HOST;
00197                         }
00198                 } else {
00199                         gotgctl.d32 = 0;
00200                         gotgctl.b.hnpreq = 1;
00201                         gotgctl.b.devhnpen = 1;
00202                         DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
00203                         DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
00204                         __DWC_ERROR("Device Not Connected/Responding\n");
00205                 }
00206         }
00207         if (gotgint.b.hstnegdet) {
00208                 /* The disconnect interrupt is set at the same time as
00209                  * Host Negotiation Detected.  During the mode
00210                  * switch all interrupts are cleared so the disconnect
00211                  * interrupt handler will not get executed.
00212                  */
00213                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
00214                             "Host Negotiation Detected++ (%s)\n",
00215                             (dwc_otg_is_host_mode(core_if) ? "Host" :
00216                              "Device"));
00217                 if (dwc_otg_is_device_mode(core_if)) {
00218                         DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
00219                                     core_if->op_state);
00220                         DWC_SPINUNLOCK(core_if->lock);
00221                         cil_hcd_disconnect(core_if);
00222                         cil_pcd_start(core_if);
00223                         DWC_SPINLOCK(core_if->lock);
00224                         core_if->op_state = A_PERIPHERAL;
00225                 } else {
00226                         /*
00227                          * Need to disable SOF interrupt immediately. When
00228                          * switching from device to host, the PCD interrupt
00229                          * handler won't handle the interrupt if host mode is
00230                          * already set. The HCD interrupt handler won't get
00231                          * called if the HCD state is HALT. This means that
00232                          * the interrupt does not get handled and Linux
00233                          * complains loudly.
00234                          */
00235                         gintmsk.d32 = 0;
00236                         gintmsk.b.sofintr = 1;
00237                         DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
00238                         DWC_SPINUNLOCK(core_if->lock);
00239                         cil_pcd_stop(core_if);
00240                         cil_hcd_start(core_if);
00241                         DWC_SPINLOCK(core_if->lock);
00242                         core_if->op_state = A_HOST;
00243                 }
00244         }
00245         if (gotgint.b.adevtoutchng) {
00246                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
00247                             "A-Device Timeout Change++\n");
00248         }
00249         if (gotgint.b.debdone) {
00250                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
00251         }
00252 
00253         /* Clear GOTGINT */
00254         DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
00255 
00256         return 1;
00257 }
00258 
00259 void w_conn_id_status_change(void *p)
00260 {
00261         dwc_otg_core_if_t *core_if = p;
00262         uint32_t count = 0;
00263         gotgctl_data_t gotgctl = {.d32 = 0 };
00264 
00265         gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
00266         DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
00267         DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
00268 
00269         /* B-Device connector (Device Mode) */
00270         if (gotgctl.b.conidsts) {
00271                 /* Wait for switch to device mode. */
00272                 while (!dwc_otg_is_device_mode(core_if)) {
00273                         DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
00274                                    (dwc_otg_is_host_mode(core_if) ? "Host" :
00275                                     "Peripheral"));
00276                         dwc_mdelay(100);
00277                         if (++count > 10000)
00278                                 break;
00279                 }
00280                 DWC_ASSERT(++count < 10000,
00281                            "Connection id status change timed out");
00282                 core_if->op_state = B_PERIPHERAL;
00283                 dwc_otg_core_init(core_if);
00284                 dwc_otg_enable_global_interrupts(core_if);
00285                 cil_pcd_start(core_if);
00286         } else {
00287                 /* A-Device connector (Host Mode) */
00288                 while (!dwc_otg_is_host_mode(core_if)) {
00289                         DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
00290                                    (dwc_otg_is_host_mode(core_if) ? "Host" :
00291                                     "Peripheral"));
00292                         dwc_mdelay(100);
00293                         if (++count > 10000)
00294                                 break;
00295                 }
00296                 DWC_ASSERT(++count < 10000,
00297                            "Connection id status change timed out");
00298                 core_if->op_state = A_HOST;
00299                 /*
00300                  * Initialize the Core for Host mode.
00301                  */
00302                 dwc_otg_core_init(core_if);
00303                 dwc_otg_enable_global_interrupts(core_if);
00304                 cil_hcd_start(core_if);
00305         }
00306 }
00307 
00319 int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
00320 {
00321 
00322         /*
00323          * Need to disable SOF interrupt immediately. If switching from device
00324          * to host, the PCD interrupt handler won't handle the interrupt if
00325          * host mode is already set. The HCD interrupt handler won't get
00326          * called if the HCD state is HALT. This means that the interrupt does
00327          * not get handled and Linux complains loudly.
00328          */
00329         gintmsk_data_t gintmsk = {.d32 = 0 };
00330         gintsts_data_t gintsts = {.d32 = 0 };
00331 
00332         gintmsk.b.sofintr = 1;
00333         DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
00334 
00335         DWC_DEBUGPL(DBG_CIL,
00336                     " ++Connector ID Status Change Interrupt++  (%s)\n",
00337                     (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
00338         
00339         DWC_SPINUNLOCK(core_if->lock);
00340 
00341         /*
00342          * Need to schedule a work, as there are possible DELAY function calls
00343          * Release lock before scheduling workq as it holds spinlock during scheduling
00344          */
00345 
00346         DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
00347                            core_if, "connection id status change");
00348         DWC_SPINLOCK(core_if->lock);
00349 
00350         /* Set flag and clear interrupt */
00351         gintsts.b.conidstschng = 1;
00352         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
00353 
00354         return 1;
00355 }
00356 
00366 int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
00367 {
00368         gintsts_data_t gintsts;
00369 
00370 #ifndef DWC_HOST_ONLY
00371         DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
00372 
00373         if (dwc_otg_is_device_mode(core_if)) {
00374                 DWC_PRINTF("SRP: Device mode\n");
00375         } else {
00376                 hprt0_data_t hprt0;
00377                 DWC_PRINTF("SRP: Host mode\n");
00378 
00379                 /* Turn on the port power bit. */
00380                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
00381                 hprt0.b.prtpwr = 1;
00382                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
00383 
00384                 /* Start the Connection timer. So a message can be displayed
00385                  * if connect does not occur within 10 seconds. */
00386                 cil_hcd_session_start(core_if);
00387         }
00388 #endif
00389 
00390         /* Clear interrupt */
00391         gintsts.d32 = 0;
00392         gintsts.b.sessreqintr = 1;
00393         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
00394 
00395         return 1;
00396 }
00397 
00398 void w_wakeup_detected(void *p)
00399 {
00400         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
00401         /*
00402          * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
00403          * so that OPT tests pass with all PHYs).
00404          */
00405         hprt0_data_t hprt0 = {.d32 = 0 };
00406 #if 0
00407         pcgcctl_data_t pcgcctl = {.d32 = 0 };
00408         /* Restart the Phy Clock */
00409         pcgcctl.b.stoppclk = 1;
00410         DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
00411         dwc_udelay(10);
00412 #endif //0
00413         hprt0.d32 = dwc_otg_read_hprt0(core_if);
00414         DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
00415 //      dwc_mdelay(70);
00416         hprt0.b.prtres = 0;     /* Resume */
00417         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
00418         DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
00419                     DWC_READ_REG32(core_if->host_if->hprt0));
00420 
00421         cil_hcd_resume(core_if);
00422 
00424         core_if->lx_state = DWC_OTG_L0;
00425 }
00426 
00434 int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
00435 {
00436         gintsts_data_t gintsts;
00437 
00438         DWC_DEBUGPL(DBG_ANY,
00439                     "++Resume and Remote Wakeup Detected Interrupt++\n");
00440 
00441         DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
00442 
00443         if (dwc_otg_is_device_mode(core_if)) {
00444                 dctl_data_t dctl = {.d32 = 0 };
00445                 DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
00446                             DWC_READ_REG32(&core_if->dev_if->
00447                                            dev_global_regs->dsts));
00448                 if (core_if->lx_state == DWC_OTG_L2) {
00449 #ifdef PARTIAL_POWER_DOWN
00450                         if (core_if->hwcfg4.b.power_optimiz) {
00451                                 pcgcctl_data_t power = {.d32 = 0 };
00452 
00453                                 power.d32 = DWC_READ_REG32(core_if->pcgcctl);
00454                                 DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
00455                                             power.d32);
00456 
00457                                 power.b.stoppclk = 0;
00458                                 DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
00459 
00460                                 power.b.pwrclmp = 0;
00461                                 DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
00462 
00463                                 power.b.rstpdwnmodule = 0;
00464                                 DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
00465                         }
00466 #endif
00467                         /* Clear the Remote Wakeup Signaling */
00468                         dctl.b.rmtwkupsig = 1;
00469                         DWC_MODIFY_REG32(&core_if->dev_if->
00470                                          dev_global_regs->dctl, dctl.d32, 0);
00471 
00472                         DWC_SPINUNLOCK(core_if->lock);
00473                         if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
00474                                 core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
00475                         }
00476                         DWC_SPINLOCK(core_if->lock);
00477                 } else {
00478                         glpmcfg_data_t lpmcfg;
00479                         lpmcfg.d32 =
00480                             DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
00481                         lpmcfg.b.hird_thres &= (~(1 << 4));
00482                         DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
00483                                         lpmcfg.d32);
00484                 }
00486                 core_if->lx_state = DWC_OTG_L0;
00487         } else {
00488                 if (core_if->lx_state != DWC_OTG_L1) {
00489                         pcgcctl_data_t pcgcctl = {.d32 = 0 };
00490 
00491                         /* Restart the Phy Clock */
00492                         pcgcctl.b.stoppclk = 1;
00493                         DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
00494                         DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
00495                 } else {
00497                         core_if->lx_state = DWC_OTG_L0;
00498                 }
00499         }
00500 
00501         /* Clear interrupt */
00502         gintsts.d32 = 0;
00503         gintsts.b.wkupintr = 1;
00504         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
00505 
00506         return 1;
00507 }
00508 
00513 static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
00514 {
00515         gpwrdn_data_t gpwrdn = { .d32 = 0 };
00516         gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
00517         gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00518 
00519         DWC_PRINTF("%s called\n", __FUNCTION__);
00520 
00521         if (!core_if->hibernation_suspend) {
00522                 DWC_PRINTF("Already exited from Hibernation\n");
00523                 return 1;
00524         }
00525 
00526         /* Switch on the voltage to the core */
00527         gpwrdn.b.pwrdnswtch = 1;
00528         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00529         dwc_udelay(10);
00530 
00531         /* Reset the core */
00532         gpwrdn.d32 = 0;
00533         gpwrdn.b.pwrdnrstn = 1;
00534         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00535         dwc_udelay(10);
00536 
00537         /* Disable power clamps*/
00538         gpwrdn.d32 = 0;
00539         gpwrdn.b.pwrdnclmp = 1;
00540         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00541 
00542         /* Remove reset the core signal */
00543         gpwrdn.d32 = 0;
00544         gpwrdn.b.pwrdnrstn = 1;
00545         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00546         dwc_udelay(10);
00547 
00548         /* Disable PMU interrupt */
00549         gpwrdn.d32 = 0;
00550         gpwrdn.b.pmuintsel = 1;
00551         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00552 
00553         core_if->hibernation_suspend = 0;
00554 
00555         /* Disable PMU */
00556         gpwrdn.d32 = 0;
00557         gpwrdn.b.pmuactv = 1;
00558         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00559         dwc_udelay(10);
00560 
00561         if (gpwrdn_temp.b.idsts) {
00562                 core_if->op_state = B_PERIPHERAL;
00563                 dwc_otg_core_init(core_if);
00564                 dwc_otg_enable_global_interrupts(core_if);
00565                 cil_pcd_start(core_if);
00566         } else {
00567                 core_if->op_state = A_HOST;
00568                 dwc_otg_core_init(core_if);
00569                 dwc_otg_enable_global_interrupts(core_if);
00570                 cil_hcd_start(core_if);
00571         }
00572 
00573         return 1;
00574 }
00575 
00580 static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
00581 {
00582         gpwrdn_data_t gpwrdn = {.d32 = 0 };
00583         DWC_DEBUGPL(DBG_ANY,
00584                     "++Powerdown Remote Wakeup Detected Interrupt++\n");
00585 
00586         if (!core_if->hibernation_suspend) {
00587                 DWC_PRINTF("Already exited from Hibernation\n");
00588                 return 1;
00589         }
00590 
00591         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00592         if (gpwrdn.b.idsts) {   // Device Mode
00593                 if ((core_if->power_down == 2)
00594                     && (core_if->hibernation_suspend == 1)) {
00595                         dwc_otg_device_hibernation_restore(core_if, 0, 0);
00596                 }
00597         } else {
00598                 if ((core_if->power_down == 2)
00599                     && (core_if->hibernation_suspend == 1)) {
00600                         dwc_otg_host_hibernation_restore(core_if, 1, 0);
00601                 }
00602         }
00603         return 1;
00604 }
00605 
00606 static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
00607 {
00608         gpwrdn_data_t gpwrdn = {.d32 = 0 };
00609         gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
00610         dwc_otg_core_if_t *core_if = otg_dev->core_if;
00611 
00612         DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
00613         gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00614         if (core_if->power_down == 2)
00615         {               
00616                 if (!core_if->hibernation_suspend) {
00617                         DWC_PRINTF("Already exited from Hibernation\n");
00618                         return 1;
00619                 }
00620                 DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
00621                 /* Switch on the voltage to the core */
00622                 gpwrdn.b.pwrdnswtch = 1;
00623                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00624                 dwc_udelay(10);
00625 
00626                 /* Reset the core */
00627                 gpwrdn.d32 = 0;
00628                 gpwrdn.b.pwrdnrstn = 1;
00629                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00630                 dwc_udelay(10);
00631 
00632                 /* Disable power clamps */
00633                 gpwrdn.d32 = 0;
00634                 gpwrdn.b.pwrdnclmp = 1;
00635                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00636 
00637                 /* Remove reset the core signal */
00638                 gpwrdn.d32 = 0;
00639                 gpwrdn.b.pwrdnrstn = 1;
00640                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00641                 dwc_udelay(10);
00642 
00643                 /* Disable PMU interrupt */
00644                 gpwrdn.d32 = 0;
00645                 gpwrdn.b.pmuintsel = 1;
00646                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00647 
00648                 /*Indicates that we are exiting from hibernation */
00649                 core_if->hibernation_suspend = 0;
00650 
00651                 /* Disable PMU */
00652                 gpwrdn.d32 = 0;
00653                 gpwrdn.b.pmuactv = 1;
00654                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00655                 dwc_udelay(10);
00656 
00657                 gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
00658                 if (gpwrdn.b.dis_vbus == 1) {
00659                         gpwrdn.d32 = 0;
00660                         gpwrdn.b.dis_vbus = 1;
00661                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00662                 }
00663 
00664                 if (gpwrdn_temp.b.idsts) {
00665                         core_if->op_state = B_PERIPHERAL;
00666                         dwc_otg_core_init(core_if);
00667                         dwc_otg_enable_global_interrupts(core_if);
00668                         cil_pcd_start(core_if);
00669                 } else {
00670                         core_if->op_state = A_HOST;
00671                         dwc_otg_core_init(core_if);
00672                         dwc_otg_enable_global_interrupts(core_if);
00673                         cil_hcd_start(core_if);
00674                 }
00675         }
00676 
00677         if (core_if->adp_enable)
00678         {
00679                 uint8_t is_host = 0;
00680                 DWC_SPINUNLOCK(core_if->lock);
00681                 /* Change the core_if's lock to hcd/pcd lock depend on mode? */
00682 #ifndef DWC_HOST_ONLY           
00683                 if (gpwrdn_temp.b.idsts)
00684                         core_if->lock = otg_dev->pcd->lock;
00685 #endif
00686 #ifndef DWC_DEVICE_ONLY
00687                 if (!gpwrdn_temp.b.idsts) {
00688                                 core_if->lock = otg_dev->hcd->lock;     
00689                                 is_host = 1;
00690                 }
00691 #endif
00692                 DWC_PRINTF("RESTART ADP\n");
00693                 if (core_if->adp.probe_enabled)         
00694                         dwc_otg_adp_probe_stop(core_if);
00695                 if (core_if->adp.sense_enabled)         
00696                         dwc_otg_adp_sense_stop(core_if);
00697                 if (core_if->adp.sense_timer_started)           
00698                         DWC_TIMER_CANCEL(core_if->adp.sense_timer);
00699                 if (core_if->adp.vbuson_timer_started)          
00700                         DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
00701                 core_if->adp.probe_timer_values[0] = -1;
00702                 core_if->adp.probe_timer_values[1] = -1;
00703                 core_if->adp.sense_timer_started = 0;
00704                 core_if->adp.vbuson_timer_started = 0;
00705                 core_if->adp.probe_counter = 0;
00706                 core_if->adp.gpwrdn = 0;
00707                 
00708                 /* Disable PMU and restart ADP */
00709                 gpwrdn_temp.d32 = 0;
00710                 gpwrdn_temp.b.pmuactv = 1;
00711                 gpwrdn_temp.b.pmuintsel = 1;
00712                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00713                 DWC_PRINTF("Check point 1\n");
00714                 dwc_mdelay(110);
00715                 dwc_otg_adp_start(core_if, is_host);
00716                 DWC_SPINLOCK(core_if->lock);
00717         }
00718         
00719 
00720         return 1;
00721 }
00722 
00723 static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
00724 {
00725         gpwrdn_data_t gpwrdn = {.d32 = 0 };
00726         int32_t otg_cap_param = core_if->core_params->otg_cap;
00727         DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
00728 
00729         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00730         if (core_if->power_down == 2) {
00731                 if (!core_if->hibernation_suspend) {
00732                         DWC_PRINTF("Already exited from Hibernation\n");
00733                         return 1;
00734                 }
00735 
00736                 if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
00737                          otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
00738                         gpwrdn.b.bsessvld == 0) {
00739                         /* Save gpwrdn register for further usage if stschng interrupt */
00740                         core_if->gr_backup->gpwrdn_local =
00741                                 DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00742                         /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
00743                         return 1;
00744                 }
00745 
00746                 /* Switch on the voltage to the core */
00747                 gpwrdn.d32 = 0;
00748                 gpwrdn.b.pwrdnswtch = 1;
00749                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00750                 dwc_udelay(10);
00751 
00752                 /* Reset the core */
00753                 gpwrdn.d32 = 0;
00754                 gpwrdn.b.pwrdnrstn = 1;
00755                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00756                 dwc_udelay(10);
00757 
00758                 /* Disable power clamps */
00759                 gpwrdn.d32 = 0;
00760                 gpwrdn.b.pwrdnclmp = 1;
00761                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00762 
00763                 /* Remove reset the core signal */
00764                 gpwrdn.d32 = 0;
00765                 gpwrdn.b.pwrdnrstn = 1;
00766                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00767                 dwc_udelay(10);
00768 
00769                 /* Disable PMU interrupt */
00770                 gpwrdn.d32 = 0;
00771                 gpwrdn.b.pmuintsel = 1;
00772                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00773                 dwc_udelay(10);
00774 
00775                 /*Indicates that we are exiting from hibernation */
00776                 core_if->hibernation_suspend = 0;
00777 
00778                 /* Disable PMU */
00779                 gpwrdn.d32 = 0;
00780                 gpwrdn.b.pmuactv = 1;
00781                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00782                 dwc_udelay(10);
00783 
00784                 core_if->op_state = B_PERIPHERAL;
00785                 dwc_otg_core_init(core_if);
00786                 dwc_otg_enable_global_interrupts(core_if);
00787                 cil_pcd_start(core_if);
00788 
00789                 if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
00790                         otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
00791                         /*
00792                          * Initiate SRP after initial ADP probe.
00793                          */
00794                         dwc_otg_initiate_srp(core_if);  
00795                 }
00796         }
00797 
00798         return 1;
00799 }
00804 static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
00805 {
00806         int retval;
00807         gpwrdn_data_t gpwrdn = {.d32 = 0 };
00808         gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
00809         dwc_otg_core_if_t *core_if = otg_dev->core_if;
00810 
00811         DWC_PRINTF("%s called\n", __FUNCTION__);
00812         
00813         if (core_if->power_down == 2) {
00814                 if (core_if->hibernation_suspend <= 0) {
00815                         DWC_PRINTF("Already exited from Hibernation\n");
00816                         return 1;
00817                 } else
00818                         gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
00819 
00820         } else {
00821                 gpwrdn_temp.d32 = core_if->adp.gpwrdn;
00822         }
00823 
00824         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00825         
00826         if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
00827                 retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
00828         } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
00829                 retval = dwc_otg_handle_pwrdn_session_change(core_if);
00830         }
00831 
00832         return retval;
00833 }
00834 
00839 static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
00840 {
00841         gpwrdn_data_t gpwrdn = {.d32 = 0 };
00842 
00843         DWC_PRINTF("%s called\n", __FUNCTION__);
00844 
00845         if (!core_if->hibernation_suspend) {
00846                 DWC_PRINTF("Already exited from Hibernation\n");
00847                 return 1;
00848         }
00849 #ifdef DWC_DEV_SRPCAP
00850         if (core_if->pwron_timer_started) {
00851                 core_if->pwron_timer_started = 0;
00852                 DWC_TIMER_CANCEL(core_if->pwron_timer);
00853         }
00854 #endif
00855 
00856         /* Switch on the voltage to the core */
00857         gpwrdn.b.pwrdnswtch = 1;
00858         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00859         dwc_udelay(10);
00860 
00861         /* Reset the core */
00862         gpwrdn.d32 = 0;
00863         gpwrdn.b.pwrdnrstn = 1;
00864         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00865         dwc_udelay(10);
00866 
00867         /* Disable power clamps */
00868         gpwrdn.d32 = 0;
00869         gpwrdn.b.pwrdnclmp = 1;
00870         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00871 
00872         /* Remove reset the core signal */
00873         gpwrdn.d32 = 0;
00874         gpwrdn.b.pwrdnrstn = 1;
00875         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00876         dwc_udelay(10);
00877 
00878         /* Disable PMU interrupt */
00879         gpwrdn.d32 = 0;
00880         gpwrdn.b.pmuintsel = 1;
00881         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00882 
00883         /* Indicates that we are exiting from hibernation */
00884         core_if->hibernation_suspend = 0;
00885 
00886         /* Disable PMU */
00887         gpwrdn.d32 = 0;
00888         gpwrdn.b.pmuactv = 1;
00889         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00890         dwc_udelay(10);
00891 
00892         /* Programm Disable VBUS to 0 */
00893         gpwrdn.d32 = 0;
00894         gpwrdn.b.dis_vbus = 1;
00895         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00896 
00897         /*Initialize the core as Host */
00898         core_if->op_state = A_HOST;
00899         dwc_otg_core_init(core_if);
00900         dwc_otg_enable_global_interrupts(core_if);
00901         cil_hcd_start(core_if);
00902 
00903         return 1;
00904 }
00905 
00908 int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
00909 {
00910         pcgcctl_data_t pcgcctl;
00911         DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
00912 
00913         //TODO De-assert restore signal. 8.a
00914         pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
00915         if (pcgcctl.b.restoremode == 1) {
00916                 gintmsk_data_t gintmsk = {.d32 = 0 };
00917                 /*
00918                  * If restore mode is Remote Wakeup,
00919                  * unmask Remote Wakeup interrupt.
00920                  */
00921                 gintmsk.b.wkupintr = 1;
00922                 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
00923                                  0, gintmsk.d32);
00924         }
00925 
00926         return 1;
00927 }
00928 
00933 int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
00934 {
00935         gintsts_data_t gintsts;
00936 
00937         DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
00938                     (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
00939                     op_state_str(core_if));
00940 
00942 #ifndef DWC_HOST_ONLY
00943         if (core_if->op_state == B_HOST) {
00944                 /* If in device mode Disconnect and stop the HCD, then
00945                  * start the PCD. */
00946                 DWC_SPINUNLOCK(core_if->lock);
00947                 cil_hcd_disconnect(core_if);
00948                 cil_pcd_start(core_if);
00949                 DWC_SPINLOCK(core_if->lock);
00950                 core_if->op_state = B_PERIPHERAL;
00951         } else if (dwc_otg_is_device_mode(core_if)) {
00952                 gotgctl_data_t gotgctl = {.d32 = 0 };
00953                 gotgctl.d32 =
00954                     DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
00955                 if (gotgctl.b.hstsethnpen == 1) {
00956                         /* Do nothing, if HNP in process the OTG
00957                          * interrupt "Host Negotiation Detected"
00958                          * interrupt will do the mode switch.
00959                          */
00960                 } else if (gotgctl.b.devhnpen == 0) {
00961                         /* If in device mode Disconnect and stop the HCD, then
00962                          * start the PCD. */
00963                         DWC_SPINUNLOCK(core_if->lock);
00964                         cil_hcd_disconnect(core_if);
00965                         cil_pcd_start(core_if);
00966                         DWC_SPINLOCK(core_if->lock);
00967                         core_if->op_state = B_PERIPHERAL;
00968                 } else {
00969                         DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
00970                 }
00971         } else {
00972                 if (core_if->op_state == A_HOST) {
00973                         /* A-Cable still connected but device disconnected. */
00974                         cil_hcd_disconnect(core_if);
00975                         if (core_if->adp_enable) {
00976                                 gpwrdn_data_t gpwrdn = { .d32 = 0 };
00977                                 cil_hcd_stop(core_if);
00978                                 /* Enable Power Down Logic */
00979                                 gpwrdn.b.pmuintsel = 1;
00980                                 gpwrdn.b.pmuactv = 1;
00981                                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00982                                 dwc_otg_adp_probe_start(core_if);
00983 
00984                                 /* Power off the core */
00985                                 if (core_if->power_down == 2) {
00986                                         gpwrdn.d32 = 0;
00987                                         gpwrdn.b.pwrdnswtch = 1;
00988                                         DWC_MODIFY_REG32(&core_if->
00989                                                          core_global_regs->
00990                                                          gpwrdn, gpwrdn.d32, 0);
00991                                 }
00992                         }
00993                 }
00994         }
00995 #endif
00996         /* Change to L3(OFF) state */
00997         core_if->lx_state = DWC_OTG_L3;
00998 
00999         gintsts.d32 = 0;
01000         gintsts.b.disconnect = 1;
01001         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
01002         return 1;
01003 }
01004 
01015 int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
01016 {
01017         dsts_data_t dsts;
01018         gintsts_data_t gintsts;
01019         dcfg_data_t dcfg;
01020 
01021         DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
01022 
01023         if (dwc_otg_is_device_mode(core_if)) {
01024                 /* Check the Device status register to determine if the Suspend
01025                  * state is active. */
01026                 dsts.d32 =
01027                     DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
01028                 DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
01029                 DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
01030                             "HWCFG4.power Optimize=%d\n",
01031                             dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
01032 
01033 #ifdef PARTIAL_POWER_DOWN
01034 
01036                 if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
01037                         pcgcctl_data_t power = {.d32 = 0 };
01038                         DWC_DEBUGPL(DBG_CIL, "suspend\n");
01039 
01040                         power.b.pwrclmp = 1;
01041                         DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
01042 
01043                         power.b.rstpdwnmodule = 1;
01044                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
01045 
01046                         power.b.stoppclk = 1;
01047                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
01048 
01049                 } else {
01050                         DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
01051                 }
01052 #endif
01053                 /* PCD callback for suspend. Release the lock inside of callback function */
01054                 cil_pcd_suspend(core_if);
01055                 if (core_if->power_down == 2)
01056                 {
01057                         dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
01058                         DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
01059                         DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
01060 
01061                         if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
01062                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
01063                                 gpwrdn_data_t gpwrdn = {.d32 = 0 };
01064                                 gusbcfg_data_t gusbcfg = {.d32 = 0 };
01065 
01066                                 /* Change to L2(suspend) state */
01067                                 core_if->lx_state = DWC_OTG_L2;
01068 
01069                                 /* Clear interrupt in gintsts */
01070                                 gintsts.d32 = 0;
01071                                 gintsts.b.usbsuspend = 1;
01072                                 DWC_WRITE_REG32(&core_if->core_global_regs->
01073                                                 gintsts, gintsts.d32);
01074                                 DWC_PRINTF("Start of hibernation completed\n");
01075                                 dwc_otg_save_global_regs(core_if);
01076                                 dwc_otg_save_dev_regs(core_if);
01077 
01078                                 gusbcfg.d32 =
01079                                     DWC_READ_REG32(&core_if->core_global_regs->
01080                                                    gusbcfg);
01081                                 if (gusbcfg.b.ulpi_utmi_sel == 1) {
01082                                         /* ULPI interface */
01083                                         /* Suspend the Phy Clock */
01084                                         pcgcctl.d32 = 0;
01085                                         pcgcctl.b.stoppclk = 1;
01086                                         DWC_MODIFY_REG32(core_if->pcgcctl, 0,
01087                                                          pcgcctl.d32);
01088                                         dwc_udelay(10);
01089                                         gpwrdn.b.pmuactv = 1;
01090                                         DWC_MODIFY_REG32(&core_if->
01091                                                          core_global_regs->
01092                                                          gpwrdn, 0, gpwrdn.d32);
01093                                 } else {
01094                                         /* UTMI+ Interface */
01095                                         gpwrdn.b.pmuactv = 1;
01096                                         DWC_MODIFY_REG32(&core_if->
01097                                                          core_global_regs->
01098                                                          gpwrdn, 0, gpwrdn.d32);
01099                                         dwc_udelay(10);
01100                                         pcgcctl.b.stoppclk = 1;
01101                                         DWC_MODIFY_REG32(core_if->pcgcctl, 0,
01102                                                          pcgcctl.d32);
01103                                         dwc_udelay(10);
01104                                 }
01105 
01106                                 /* Set flag to indicate that we are in hibernation */
01107                                 core_if->hibernation_suspend = 1;
01108                                 /* Enable interrupts from wake up logic */
01109                                 gpwrdn.d32 = 0;
01110                                 gpwrdn.b.pmuintsel = 1;
01111                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
01112                                                  gpwrdn, 0, gpwrdn.d32);
01113                                 dwc_udelay(10);
01114 
01115                                 /* Unmask device mode interrupts in GPWRDN */
01116                                 gpwrdn.d32 = 0;
01117                                 gpwrdn.b.rst_det_msk = 1;
01118                                 gpwrdn.b.lnstchng_msk = 1;
01119                                 gpwrdn.b.sts_chngint_msk = 1;
01120                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
01121                                                  gpwrdn, 0, gpwrdn.d32);
01122                                 dwc_udelay(10);
01123 
01124                                 /* Enable Power Down Clamp */
01125                                 gpwrdn.d32 = 0;
01126                                 gpwrdn.b.pwrdnclmp = 1;
01127                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
01128                                                  gpwrdn, 0, gpwrdn.d32);
01129                                 dwc_udelay(10);
01130 
01131                                 /* Switch off VDD */
01132                                 gpwrdn.d32 = 0;
01133                                 gpwrdn.b.pwrdnswtch = 1;
01134                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
01135                                                  gpwrdn, 0, gpwrdn.d32);
01136 
01137                                 /* Save gpwrdn register for further usage if stschng interrupt */
01138                                 core_if->gr_backup->gpwrdn_local =
01139                                                         DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
01140                                 DWC_PRINTF("Hibernation completed\n");
01141 
01142                                 return 1;
01143                         }
01144                 }
01145         } else {
01146                 if (core_if->op_state == A_PERIPHERAL) {
01147                         DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
01148                         /* Clear the a_peripheral flag, back to a_host. */
01149                         DWC_SPINUNLOCK(core_if->lock);
01150                         cil_pcd_stop(core_if);
01151                         cil_hcd_start(core_if);
01152                         DWC_SPINLOCK(core_if->lock);
01153                         core_if->op_state = A_HOST;
01154                 }
01155         }
01156 
01157         /* Change to L2(suspend) state */
01158         core_if->lx_state = DWC_OTG_L2;
01159 
01160         /* Clear interrupt */
01161         gintsts.d32 = 0;
01162         gintsts.b.usbsuspend = 1;
01163         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
01164 
01165         return 1;
01166 }
01167 
01168 #ifdef CONFIG_USB_DWC_OTG_LPM
01169 
01172 static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
01173 {
01174         glpmcfg_data_t lpmcfg;
01175         gintsts_data_t gintsts;
01176 
01177         if (!core_if->core_params->lpm_enable) {
01178                 DWC_PRINTF("Unexpected LPM interrupt\n");
01179         }
01180 
01181         lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
01182         DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
01183 
01184         if (dwc_otg_is_host_mode(core_if)) {
01185                 cil_hcd_sleep(core_if);
01186         } else {
01187                 lpmcfg.b.hird_thres |= (1 << 4);
01188                 DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
01189                                 lpmcfg.d32);
01190         }
01191 
01192         /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
01193         dwc_udelay(10);
01194         lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
01195         if (lpmcfg.b.prt_sleep_sts) {
01196                 /* Save the current state */
01197                 core_if->lx_state = DWC_OTG_L1;
01198         }
01199 
01200         /* Clear interrupt  */
01201         gintsts.d32 = 0;
01202         gintsts.b.lpmtranrcvd = 1;
01203         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
01204         return 1;
01205 }
01206 #endif /* CONFIG_USB_DWC_OTG_LPM */
01207 
01211 static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
01212 {
01213         gahbcfg_data_t gahbcfg = {.d32 = 0 };
01214         gintsts_data_t gintsts;
01215         gintmsk_data_t gintmsk;
01216         gintmsk_data_t gintmsk_common = {.d32 = 0 };
01217         gintmsk_common.b.wkupintr = 1;
01218         gintmsk_common.b.sessreqintr = 1;
01219         gintmsk_common.b.conidstschng = 1;
01220         gintmsk_common.b.otgintr = 1;
01221         gintmsk_common.b.modemismatch = 1;
01222         gintmsk_common.b.disconnect = 1;
01223         gintmsk_common.b.usbsuspend = 1;
01224 #ifdef CONFIG_USB_DWC_OTG_LPM
01225         gintmsk_common.b.lpmtranrcvd = 1;
01226 #endif
01227         gintmsk_common.b.restoredone = 1;
01231         gintmsk_common.b.portintr = 1;
01232 
01233         gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
01234         gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
01235         gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
01236 
01237 #ifdef DEBUG
01238         /* if any common interrupts set */
01239         if (gintsts.d32 & gintmsk_common.d32) {
01240                 DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
01241                             gintsts.d32, gintmsk.d32);
01242         }
01243 #endif
01244         if (gahbcfg.b.glblintrmsk)      
01245                 return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
01246         else
01247                 return 0;
01248 
01249 }
01250 
01251 /* MACRO for clearing interupt bits in GPWRDN register */
01252 #define CLEAR_GPWRDN_INTR(__core_if,__intr) \
01253 do { \
01254                 gpwrdn_data_t gpwrdn = {.d32=0}; \
01255                 gpwrdn.b.__intr = 1; \
01256                 DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
01257                 0, gpwrdn.d32); \
01258 } while (0)
01259 
01275 int32_t dwc_otg_handle_common_intr(void *dev)
01276 {
01277         int retval = 0;
01278         gintsts_data_t gintsts;
01279         gpwrdn_data_t gpwrdn = {.d32 = 0 };
01280         dwc_otg_device_t *otg_dev = dev;
01281         dwc_otg_core_if_t *core_if = otg_dev->core_if;
01282         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
01283         if (dwc_otg_is_device_mode(core_if))
01284                 core_if->frame_num = dwc_otg_get_frame_number(core_if);
01285                 
01286         if (core_if->lock)
01287                 DWC_SPINLOCK(core_if->lock);
01288 
01289         if (core_if->hibernation_suspend <= 0) {
01290                 gintsts.d32 = dwc_otg_read_common_intr(core_if);
01291 
01292                 if (gintsts.b.modemismatch) {
01293                         retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
01294                 }
01295                 if (gintsts.b.otgintr) {
01296                         retval |= dwc_otg_handle_otg_intr(core_if);
01297                 }
01298                 if (gintsts.b.conidstschng) {
01299                         retval |= dwc_otg_handle_conn_id_status_change_intr(core_if);
01300                 }
01301                 if (gintsts.b.disconnect) {
01302                         retval |= dwc_otg_handle_disconnect_intr(core_if);
01303                 }
01304                 if (gintsts.b.sessreqintr) {
01305                         retval |= dwc_otg_handle_session_req_intr(core_if);
01306                 }
01307                 if (gintsts.b.wkupintr) {
01308                         retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
01309                 }
01310                 if (gintsts.b.usbsuspend) {
01311                         retval |= dwc_otg_handle_usb_suspend_intr(core_if);
01312                 }
01313 #ifdef CONFIG_USB_DWC_OTG_LPM
01314                 if (gintsts.b.lpmtranrcvd) {
01315                         retval |= dwc_otg_handle_lpm_intr(core_if);
01316                 }
01317 #endif
01318                 if (gintsts.b.restoredone) {
01319                         gintsts.d32 = 0;
01320                         if (core_if->power_down == 2)
01321                                 core_if->hibernation_suspend = -1;
01322                         gintsts.b.restoredone = 1;
01323                         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
01324                         DWC_PRINTF(" --Restore done interrupt received-- \n");
01325                         retval |= 1;
01326                 }
01327                 if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
01328                         /* The port interrupt occurs while in device mode with HPRT0
01329                          * Port Enable/Disable.
01330                          */
01331                         gintsts.d32 = 0;
01332                         gintsts.b.portintr = 1;
01333                         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
01334                         retval |= 1;
01335 
01336                 }
01337         } else {
01338                 DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
01339 
01340                 if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
01341                         CLEAR_GPWRDN_INTR(core_if, disconn_det);
01342                         if (gpwrdn.b.linestate == 0) {
01343                                 dwc_otg_handle_pwrdn_disconnect_intr(core_if);
01344                         } else {
01345                                 DWC_PRINTF("Disconnect detected while linestate is not 0\n");
01346                         }
01347 
01348                         retval |= 1;
01349                 }
01350                 if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
01351                         CLEAR_GPWRDN_INTR(core_if, lnstschng);
01352                         /* remote wakeup from hibernation */
01353                         if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
01354                                 dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
01355                         } else {
01356                                 DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
01357                         }
01358                         retval |= 1;
01359                 }
01360                 if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
01361                         CLEAR_GPWRDN_INTR(core_if, rst_det);
01362                         if (gpwrdn.b.linestate == 0) {
01363                                 DWC_PRINTF("Reset detected\n");
01364                                 retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
01365                         }
01366                 }
01367                 if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
01368                         CLEAR_GPWRDN_INTR(core_if, srp_det);
01369                         dwc_otg_handle_pwrdn_srp_intr(core_if);
01370                         retval |= 1;
01371                 }
01372         }
01373         /* Handle ADP interrupt here */
01374         if (gpwrdn.b.adp_int) {
01375                 DWC_PRINTF("ADP interrupt\n");
01376                 CLEAR_GPWRDN_INTR(core_if, adp_int);
01377                 dwc_otg_adp_handle_intr(core_if);
01378                 retval |= 1;
01379         }
01380         if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
01381                 DWC_PRINTF("STS CHNG interrupt asserted\n");
01382                 CLEAR_GPWRDN_INTR(core_if, sts_chngint);
01383                 dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
01384 
01385                 retval |= 1;
01386         }
01387         if (core_if->lock)
01388                 DWC_SPINUNLOCK(core_if->lock);
01389 
01390         return retval;
01391 }

Generated on Thu Oct 27 03:56:37 2011 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.3.9.1