USB: fix Coding Style.
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / dwc_otg_cil_intr.c
1 /* ==========================================================================
2  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
3  * $Revision: #35 $
4  * $Date: 2012/12/21 $
5  * $Change: 2131568 $
6  *
7  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9  * otherwise expressly agreed to in writing between Synopsys and you.
10  *
11  * The Software IS NOT an item of Licensed Software or Licensed Product under
12  * any End User Software License Agreement or Agreement for Licensed Product
13  * with Synopsys or any supplement thereto. You are permitted to use and
14  * redistribute this Software in source and binary forms, with or without
15  * modification, provided that redistributions of source code must retain this
16  * notice. You may not view, use, disclose, copy or distribute this file or
17  * any information contained herein except pursuant to this license grant from
18  * Synopsys. If you do not agree with this notice, including the disclaimer
19  * below, then you are not authorized to use the Software.
20  *
21  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31  * DAMAGE.
32  * ========================================================================== */
33
34 /** @file
35  *
36  * The Core Interface Layer provides basic services for accessing and
37  * managing the DWC_otg hardware. These services are used by both the
38  * Host Controller Driver and the Peripheral Controller Driver.
39  *
40  * This file contains the Common Interrupt handlers.
41  */
42 #include "common_port/dwc_os.h"
43 #include "dwc_otg_regs.h"
44 #include "dwc_otg_cil.h"
45 #include "dwc_otg_driver.h"
46 #include "dwc_otg_pcd.h"
47 #include "dwc_otg_hcd.h"
48 #include "usbdev_rk.h"
49
50 #ifdef DEBUG
51 inline const char *op_state_str(dwc_otg_core_if_t *core_if)
52 {
53         return (core_if->op_state == A_HOST ? "a_host" :
54                 (core_if->op_state == A_SUSPEND ? "a_suspend" :
55                  (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
56                   (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
57                    (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
58 }
59 #endif
60
61 /** This function will log a debug message
62  *
63  * @param core_if Programming view of DWC_otg controller.
64  */
65 int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t *core_if)
66 {
67         gintsts_data_t gintsts;
68         DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
69                  dwc_otg_mode(core_if) ? "Host" : "Device");
70
71         /* Clear interrupt */
72         gintsts.d32 = 0;
73         gintsts.b.modemismatch = 1;
74         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
75         return 1;
76 }
77
78 /**
79  * This function handles the OTG Interrupts. It reads the OTG
80  * Interrupt Register (GOTGINT) to determine what interrupt has
81  * occurred.
82  *
83  * @param core_if Programming view of DWC_otg controller.
84  */
85 int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *core_if)
86 {
87         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
88         gotgint_data_t gotgint;
89         gotgctl_data_t gotgctl;
90         gintmsk_data_t gintmsk;
91         gpwrdn_data_t gpwrdn;
92         dctl_data_t dctl = {.d32 = 0 };
93
94         gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
95         gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
96         DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
97                     op_state_str(core_if));
98
99         if (gotgint.b.sesenddet) {
100                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
101                             "Session End Detected++ (%s)\n",
102                             op_state_str(core_if));
103
104                 /* do soft disconnect */
105                 dctl.d32 =
106                     DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
107                 dctl.b.sftdiscon = 1;
108                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
109                                 dctl.d32);
110                 dwc_otg_disable_global_interrupts(core_if);
111                 core_if->otg_dev->pcd->vbus_status = USB_BC_TYPE_DISCNT;
112                 DWC_PRINTF
113                     ("********session end ,soft disconnect************************\n");
114
115                 gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
116
117                 if (core_if->op_state == B_HOST) {
118                         cil_pcd_start(core_if);
119                         core_if->op_state = B_PERIPHERAL;
120                 } else {
121                         /* If not B_HOST and Device HNP still set. HNP
122                          * Did not succeed!*/
123                         if (gotgctl.b.devhnpen) {
124                                 DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
125                                 __DWC_ERROR
126                                     ("Device Not Connected/Responding!\n");
127                         }
128
129                         /* If Session End Detected the B-Cable has
130                          * been disconnected. */
131                         /* Reset PCD and Gadget driver to a
132                          * clean state. */
133                         core_if->lx_state = DWC_OTG_L0;
134                         DWC_SPINUNLOCK(core_if->lock);
135                         cil_pcd_stop(core_if);
136                         DWC_SPINLOCK(core_if->lock);
137
138                         if (core_if->otg_ver) {
139                                 /** PET testing*/
140                                 gotgctl.d32 = 0;
141                                 gotgctl.b.devhnpen = 1;
142                                 DWC_MODIFY_REG32(&global_regs->gotgctl,
143                                                  gotgctl.d32, 0);
144                                 if (core_if->test_mode == 6) {
145                                         /* manukz: old value was 50 */
146                                         DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
147                                                                    dwc_otg_initiate_srp,
148                                                                    core_if, 3000,
149                                                                    "initate SRP");
150                                         core_if->test_mode = 0;
151                                 } else if (core_if->adp_enable) {
152                                         if (core_if->power_down == 2) {
153                                                 gpwrdn.d32 = 0;
154                                                 gpwrdn.b.pwrdnswtch = 1;
155                                                 DWC_MODIFY_REG32
156                                                     (&core_if->core_global_regs->gpwrdn,
157                                                      gpwrdn.d32, 0);
158                                         }
159
160                                         gpwrdn.d32 = 0;
161                                         gpwrdn.b.pmuintsel = 1;
162                                         gpwrdn.b.pmuactv = 1;
163                                         DWC_MODIFY_REG32(&core_if->
164                                                          core_global_regs->
165                                                          gpwrdn, 0, gpwrdn.d32);
166                                         dwc_otg_adp_sense_start(core_if);
167                                 }
168                         }
169                 }
170                 if (core_if->otg_ver == 0) {
171                         gotgctl.d32 = 0;
172                         gotgctl.b.devhnpen = 1;
173                         DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
174                 }
175         }
176         if (gotgint.b.sesreqsucstschng) {
177                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
178                             "Session Reqeust Success Status Change++\n");
179                 gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
180                 if (gotgctl.b.sesreqscs) {
181
182                         if ((core_if->core_params->phy_type ==
183                              DWC_PHY_TYPE_PARAM_FS)
184                             && (core_if->core_params->i2c_enable)) {
185                                 core_if->srp_success = 1;
186                         } else {
187                                 DWC_SPINUNLOCK(core_if->lock);
188                                 cil_pcd_resume(core_if);
189                                 DWC_SPINLOCK(core_if->lock);
190                                 /* Clear Session Request */
191                                 gotgctl.d32 = 0;
192                                 gotgctl.b.sesreq = 1;
193                                 DWC_MODIFY_REG32(&global_regs->gotgctl,
194                                                  gotgctl.d32, 0);
195                         }
196                 }
197         }
198         if (gotgint.b.hstnegsucstschng) {
199                 /* Print statements during the HNP interrupt handling
200                  * can cause it to fail.*/
201                 gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
202                 /* WA for 3.00a- HW is not setting cur_mode, even sometimes
203                  * this does not help*/
204                 if (core_if->snpsid >= OTG_CORE_REV_3_00a)
205                         dwc_udelay(100);
206                 if (gotgctl.b.hstnegscs) {
207                         if (dwc_otg_is_host_mode(core_if)) {
208                                 core_if->op_state = B_HOST;
209                                 /*
210                                  * Need to disable SOF interrupt immediately.
211                                  * When switching from device to host, the PCD
212                                  * interrupt handler won't handle the
213                                  * interrupt if host mode is already set. The
214                                  * HCD interrupt handler won't get called if
215                                  * the HCD state is HALT. This means that the
216                                  * interrupt does not get handled and Linux
217                                  * complains loudly.
218                                  */
219                                 gintmsk.d32 = 0;
220                                 gintmsk.b.sofintr = 1;
221                                 /* gintmsk.b.usbsuspend = 1; */
222                                 DWC_MODIFY_REG32(&global_regs->gintmsk,
223                                                  gintmsk.d32, 0);
224                                 /* Call callback function with spin lock released */
225                                 DWC_SPINUNLOCK(core_if->lock);
226                                 cil_pcd_stop(core_if);
227                                 /*
228                                  * Initialize the Core for Host mode.
229                                  */
230                                 cil_hcd_start(core_if);
231                                 DWC_SPINLOCK(core_if->lock);
232                         }
233                 } else {
234                         gotgctl.d32 = 0;
235                         gotgctl.b.hnpreq = 1;
236                         gotgctl.b.devhnpen = 1;
237                         DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
238                         DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
239                         __DWC_ERROR("Device Not Connected/Responding\n");
240                 }
241         }
242         if (gotgint.b.hstnegdet) {
243                 /* The disconnect interrupt is set at the same time as
244                  * Host Negotiation Detected.  During the mode
245                  * switch all interrupts are cleared so the disconnect
246                  * interrupt handler will not get executed.
247                  */
248                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
249                             "Host Negotiation Detected++ (%s)\n",
250                             (dwc_otg_is_host_mode(core_if) ? "Host" :
251                              "Device"));
252                 if (dwc_otg_is_device_mode(core_if)) {
253                         DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
254                                     core_if->op_state);
255                         DWC_SPINUNLOCK(core_if->lock);
256                         cil_hcd_disconnect(core_if);
257                         cil_pcd_start(core_if);
258                         DWC_SPINLOCK(core_if->lock);
259                         core_if->op_state = A_PERIPHERAL;
260                 } else {
261                         /*
262                          * Need to disable SOF interrupt immediately. When
263                          * switching from device to host, the PCD interrupt
264                          * handler won't handle the interrupt if host mode is
265                          * already set. The HCD interrupt handler won't get
266                          * called if the HCD state is HALT. This means that
267                          * the interrupt does not get handled and Linux
268                          * complains loudly.
269                          */
270                         gintmsk.d32 = 0;
271                         gintmsk.b.sofintr = 1;
272                         DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
273                         DWC_SPINUNLOCK(core_if->lock);
274                         cil_pcd_stop(core_if);
275                         cil_hcd_start(core_if);
276                         DWC_SPINLOCK(core_if->lock);
277                         core_if->op_state = A_HOST;
278                 }
279         }
280         if (gotgint.b.adevtoutchng) {
281                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
282                             "A-Device Timeout Change++\n");
283         }
284         if (gotgint.b.debdone) {
285                 DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
286                 /* Need to power off VBUS after 10s if OTG2 non-hnp capable host */
287                 if (core_if->otg_ver == 1)
288                         cil_hcd_session_start(core_if);
289         }
290
291         /* Clear GOTGINT */
292         DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
293
294         return 1;
295 }
296
297 void w_conn_id_status_change(void *p)
298 {
299         dwc_otg_core_if_t *core_if = p;
300         uint32_t count = 0;
301         gotgctl_data_t gotgctl = {.d32 = 0 };
302         dwc_otg_pcd_t *pcd = core_if->otg_dev->pcd;
303
304         gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
305         DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
306         DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
307
308         /* B-Device connector (Device Mode) */
309         if (gotgctl.b.conidsts) {
310                 gotgctl_data_t gotgctl_local;
311
312                 /* Wait for switch to device mode. */
313                 while (!dwc_otg_is_device_mode(core_if)) {
314                         gotgctl_local.d32 =
315                             DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
316                         DWC_DEBUGPL(DBG_ANY,
317                                     "Waiting for Peripheral Mode, Mode=%s count = %d gotgctl=%08x\n",
318                                     (dwc_otg_is_host_mode(core_if) ? "Host" :
319                                      "Peripheral"), count, gotgctl_local.d32);
320                         dwc_mdelay(1);  /* vahrama previous value was 100 */
321                         if (!gotgctl_local.b.conidsts)
322                                 goto host;
323                         if (++count > 10000)
324                                 break;
325                 }
326                 DWC_ASSERT(++count < 10000,
327                            "Connection id status change timed out");
328                 core_if->op_state = B_PERIPHERAL;
329                 cil_hcd_stop(core_if);;
330                 /* pcd->phy_suspend = 1; */
331                 pcd->vbus_status = 0;
332                 dwc_otg_pcd_start_check_vbus_work(pcd);
333                 if (core_if->otg_ver == 0)
334                         dwc_otg_core_init(core_if);
335                 dwc_otg_enable_global_interrupts(core_if);
336                 cil_pcd_start(core_if);
337         } else {
338 host:
339                 /* A-Device connector (Host Mode) */
340                 while (!dwc_otg_is_host_mode(core_if)) {
341                         DWC_DEBUGPL(DBG_ANY, "Waiting for Host Mode, Mode=%s\n",
342                                     (dwc_otg_is_host_mode(core_if) ? "Host" :
343                                      "Peripheral"));
344                         dwc_mdelay(1);  /* vahrama previously was 100 */
345                         if (++count > 10000)
346                                 break;
347                 }
348                 DWC_ASSERT(++count < 10000,
349                            "Connection id status change timed out");
350                 core_if->op_state = A_HOST;
351
352                 cancel_delayed_work(&pcd->check_vbus_work);
353
354                 /*
355                  * Initialize the Core for Host mode.
356                  */
357                 if (core_if->otg_ver)
358                         /* To power off the bus in 10s from the beginning
359                          * of test while denounce has not come yet */
360                         cil_hcd_session_start(core_if);
361                 else
362                         dwc_otg_core_init(core_if);
363                 dwc_otg_enable_global_interrupts(core_if);
364                 cil_hcd_start(core_if);
365         }
366 }
367
368 /**
369  * This function handles the Connector ID Status Change Interrupt.  It
370  * reads the OTG Interrupt Register (GOTCTL) to determine whether this
371  * is a Device to Host Mode transition or a Host Mode to Device
372  * Transition.
373  *
374  * This only occurs when the cable is connected/removed from the PHY
375  * connector.
376  *
377  * @param core_if Programming view of DWC_otg controller.
378  */
379 int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *core_if)
380 {
381
382         /*
383          * Need to disable SOF interrupt immediately. If switching from device
384          * to host, the PCD interrupt handler won't handle the interrupt if
385          * host mode is already set. The HCD interrupt handler won't get
386          * called if the HCD state is HALT. This means that the interrupt does
387          * not get handled and Linux complains loudly.
388          */
389         gintmsk_data_t gintmsk = {.d32 = 0 };
390         gintsts_data_t gintsts = {.d32 = 0 };
391
392         if (core_if->usb_mode != USB_MODE_NORMAL)
393                 goto out;
394
395         gintmsk.b.sofintr = 1;
396         DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
397         DWC_DEBUGPL(DBG_CIL,
398                     " ++Connector ID Status Change Interrupt++  (%s)\n",
399                     (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
400
401         DWC_SPINUNLOCK(core_if->lock);
402
403         /*
404          * Need to schedule a work, as there are possible DELAY function calls
405          * Release lock before scheduling workq as it holds spinlock during scheduling
406          */
407
408         DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
409                            core_if, "connection id status change");
410         DWC_SPINLOCK(core_if->lock);
411 out:
412         /* Set flag and clear interrupt */
413         gintsts.b.conidstschng = 1;
414         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
415
416         return 1;
417 }
418
419 /**
420  * This interrupt indicates that a device is initiating the Session
421  * Request Protocol to request the host to turn on bus power so a new
422  * session can begin. The handler responds by turning on bus power. If
423  * the DWC_otg controller is in low power mode, the handler brings the
424  * controller out of low power mode before turning on bus power.
425  *
426  * @param core_if Programming view of DWC_otg controller.
427  */
428 int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t *core_if)
429 {
430         gintsts_data_t gintsts;
431
432 #ifndef DWC_HOST_ONLY
433         DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
434         if (dwc_otg_is_device_mode(core_if)) {
435                 gotgctl_data_t gotgctl = {.d32 = 0 };
436                 DWC_PRINTF("SRP: Device mode\n");
437                 gotgctl.d32 =
438                     DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
439                 if (gotgctl.b.sesreqscs)
440                         DWC_PRINTF("SRP Success\n");
441                 else
442                         DWC_PRINTF("SRP Fail\n");
443                 if (core_if->otg_ver) {
444                         gotgctl.d32 = 0;
445                         gotgctl.b.devhnpen = 1;
446                         DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
447                                          gotgctl.d32, 0);
448                 }
449         } else {
450                 hprt0_data_t hprt0;
451                 DWC_PRINTF("SRP: Host mode\n");
452
453                 /* Turn on the port power bit. */
454                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
455                 hprt0.b.prtpwr = 1;
456                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
457
458                 /* Start the Connection timer. So a message can be displayed
459                  * if connect does not occur within 10 seconds. */
460                 cil_hcd_session_start(core_if);
461         }
462 #endif
463
464         /* Clear interrupt */
465         gintsts.d32 = 0;
466         gintsts.b.sessreqintr = 1;
467         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
468
469         return 1;
470 }
471
472 void w_wakeup_detected(void *data)
473 {
474         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) data;
475         /*
476          * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
477          * so that OPT tests pass with all PHYs).
478          */
479         hprt0_data_t hprt0 = {.d32 = 0 };
480 #if 0
481         pcgcctl_data_t pcgcctl = {.d32 = 0 };
482         /* Restart the Phy Clock */
483         pcgcctl.b.stoppclk = 1;
484         DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
485         dwc_udelay(10);
486 #endif
487         hprt0.d32 = dwc_otg_read_hprt0(core_if);
488         DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
489         dwc_mdelay(70);
490         hprt0.b.prtres = 0;     /* Resume */
491         DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
492         DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
493                     DWC_READ_REG32(core_if->host_if->hprt0));
494
495         cil_hcd_resume(core_if);
496
497         /** Change to L0 state*/
498         core_if->lx_state = DWC_OTG_L0;
499 }
500
501 /**
502  * This interrupt indicates that the DWC_otg controller has detected a
503  * resume or remote wakeup sequence. If the DWC_otg controller is in
504  * low power mode, the handler must brings the controller out of low
505  * power mode. The controller automatically begins resume
506  * signaling. The handler schedules a time to stop resume signaling.
507  */
508 int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t *core_if)
509 {
510         gintsts_data_t gintsts;
511
512         DWC_DEBUGPL(DBG_ANY,
513                     "++Resume and Remote Wakeup Detected Interrupt++\n");
514
515         DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
516
517         if (dwc_otg_is_device_mode(core_if)) {
518                 dctl_data_t dctl = {.d32 = 0 };
519                 DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
520                             DWC_READ_REG32(&core_if->dev_if->
521                                            dev_global_regs->dsts));
522                 if (core_if->lx_state == DWC_OTG_L2) {
523 #ifdef PARTIAL_POWER_DOWN
524                         if (core_if->hwcfg4.b.power_optimiz) {
525                                 pcgcctl_data_t power = {.d32 = 0 };
526
527                                 power.d32 = DWC_READ_REG32(core_if->pcgcctl);
528                                 DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
529                                             power.d32);
530
531                                 power.b.stoppclk = 0;
532                                 DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
533
534                                 power.b.pwrclmp = 0;
535                                 DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
536
537                                 power.b.rstpdwnmodule = 0;
538                                 DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
539                         }
540 #endif
541                         /* Clear the Remote Wakeup Signaling */
542                         dctl.b.rmtwkupsig = 1;
543                         DWC_MODIFY_REG32(&core_if->dev_if->
544                                          dev_global_regs->dctl, dctl.d32, 0);
545
546                         DWC_SPINUNLOCK(core_if->lock);
547                         if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
548                                 core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->
549                                                                p);
550                         }
551                         DWC_SPINLOCK(core_if->lock);
552                 } else {
553                         glpmcfg_data_t lpmcfg;
554                         pcgcctl_data_t pcgcctl = {.d32 = 0 };
555
556                         lpmcfg.d32 =
557                             DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
558                         lpmcfg.b.hird_thres &= (~(1 << 4));
559                         lpmcfg.b.en_utmi_sleep = 0;
560
561                         /* Clear Enbl_L1Gating bit. */
562                         pcgcctl.b.enbl_sleep_gating = 1;
563                         DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
564
565                         DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
566                                         lpmcfg.d32);
567                 }
568                 /** Change to L0 state*/
569                 core_if->lx_state = DWC_OTG_L0;
570         } else {
571                 if (core_if->lx_state != DWC_OTG_L1) {
572                         pcgcctl_data_t pcgcctl = {.d32 = 0 };
573
574                         /* Restart the Phy Clock */
575                         pcgcctl.b.stoppclk = 1;
576                         DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
577                         DWC_TASK_SCHEDULE(core_if->wkp_tasklet);
578                 } else {
579                         /** Change to L0 state*/
580                         core_if->lx_state = DWC_OTG_L0;
581                 }
582         }
583
584         /* Clear interrupt */
585         gintsts.d32 = 0;
586         gintsts.b.wkupintr = 1;
587         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
588
589         return 1;
590 }
591
592 /**
593  * This interrupt indicates that the Wakeup Logic has detected a
594  * Device disconnect.
595  */
596 static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
597 {
598         gpwrdn_data_t gpwrdn = {.d32 = 0 };
599         gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
600         gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
601
602         DWC_PRINTF("%s called\n", __FUNCTION__);
603
604         if (!core_if->hibernation_suspend) {
605                 DWC_PRINTF("Already exited from Hibernation\n");
606                 return 1;
607         }
608
609         /* Switch on the voltage to the core */
610         gpwrdn.b.pwrdnswtch = 1;
611         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
612         dwc_udelay(10);
613
614         /* Reset the core */
615         gpwrdn.d32 = 0;
616         gpwrdn.b.pwrdnrstn = 1;
617         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
618         dwc_udelay(10);
619
620         /* Disable power clamps */
621         gpwrdn.d32 = 0;
622         gpwrdn.b.pwrdnclmp = 1;
623         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
624
625         /* Remove reset the core signal */
626         gpwrdn.d32 = 0;
627         gpwrdn.b.pwrdnrstn = 1;
628         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
629         dwc_udelay(10);
630
631         /* Disable PMU interrupt */
632         gpwrdn.d32 = 0;
633         gpwrdn.b.pmuintsel = 1;
634         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
635
636         core_if->hibernation_suspend = 0;
637
638         /* Disable PMU */
639         gpwrdn.d32 = 0;
640         gpwrdn.b.pmuactv = 1;
641         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
642         dwc_udelay(10);
643
644         if (gpwrdn_temp.b.idsts) {
645                 core_if->op_state = B_PERIPHERAL;
646                 dwc_otg_core_init(core_if);
647                 dwc_otg_enable_global_interrupts(core_if);
648                 cil_pcd_start(core_if);
649         } else {
650                 core_if->op_state = A_HOST;
651                 dwc_otg_core_init(core_if);
652                 dwc_otg_enable_global_interrupts(core_if);
653                 cil_hcd_start(core_if);
654         }
655
656         return 1;
657 }
658
659 /**
660  * This interrupt indicates that the Wakeup Logic has detected a
661  * remote wakeup sequence.
662  */
663 static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t *
664                                                          core_if)
665 {
666         gpwrdn_data_t gpwrdn = {.d32 = 0 };
667         DWC_DEBUGPL(DBG_ANY,
668                     "++Powerdown Remote Wakeup Detected Interrupt++\n");
669
670         if (!core_if->hibernation_suspend) {
671                 DWC_PRINTF("Already exited from Hibernation\n");
672                 return 1;
673         }
674
675         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
676         if (gpwrdn.b.idsts) {   /* Device Mode */
677                 if ((core_if->power_down == 2)
678                     && (core_if->hibernation_suspend == 1)) {
679                         dwc_otg_device_hibernation_restore(core_if, 0, 0);
680                 }
681         } else {
682                 if ((core_if->power_down == 2)
683                     && (core_if->hibernation_suspend == 1)) {
684                         dwc_otg_host_hibernation_restore(core_if, 1, 0);
685                 }
686         }
687         return 1;
688 }
689
690 static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
691 {
692         gpwrdn_data_t gpwrdn = {.d32 = 0 };
693         gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
694         dwc_otg_core_if_t *core_if = otg_dev->core_if;
695
696         DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
697         gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
698         if (core_if->power_down == 2) {
699                 if (!core_if->hibernation_suspend) {
700                         DWC_PRINTF("Already exited from Hibernation\n");
701                         return 1;
702                 }
703                 DWC_DEBUGPL(DBG_ANY,
704                             "Exit from hibernation on ID sts change\n");
705                 /* Switch on the voltage to the core */
706                 gpwrdn.b.pwrdnswtch = 1;
707                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
708                                  0);
709                 dwc_udelay(10);
710
711                 /* Reset the core */
712                 gpwrdn.d32 = 0;
713                 gpwrdn.b.pwrdnrstn = 1;
714                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
715                                  0);
716                 dwc_udelay(10);
717
718                 /* Disable power clamps */
719                 gpwrdn.d32 = 0;
720                 gpwrdn.b.pwrdnclmp = 1;
721                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
722                                  0);
723
724                 /* Remove reset the core signal */
725                 gpwrdn.d32 = 0;
726                 gpwrdn.b.pwrdnrstn = 1;
727                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
728                                  gpwrdn.d32);
729                 dwc_udelay(10);
730
731                 /* Disable PMU interrupt */
732                 gpwrdn.d32 = 0;
733                 gpwrdn.b.pmuintsel = 1;
734                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
735                                  0);
736
737                 /*Indicates that we are exiting from hibernation */
738                 core_if->hibernation_suspend = 0;
739
740                 /* Disable PMU */
741                 gpwrdn.d32 = 0;
742                 gpwrdn.b.pmuactv = 1;
743                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
744                                  0);
745                 dwc_udelay(10);
746
747                 gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
748                 if (gpwrdn.b.dis_vbus == 1) {
749                         gpwrdn.d32 = 0;
750                         gpwrdn.b.dis_vbus = 1;
751                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
752                                          gpwrdn.d32, 0);
753                 }
754
755                 if (gpwrdn_temp.b.idsts) {
756                         core_if->op_state = B_PERIPHERAL;
757                         dwc_otg_core_init(core_if);
758                         dwc_otg_enable_global_interrupts(core_if);
759                         cil_pcd_start(core_if);
760                 } else {
761                         core_if->op_state = A_HOST;
762                         dwc_otg_core_init(core_if);
763                         dwc_otg_enable_global_interrupts(core_if);
764                         cil_hcd_start(core_if);
765                 }
766         }
767
768         if (core_if->adp_enable) {
769                 uint8_t is_host = 0;
770                 DWC_SPINUNLOCK(core_if->lock);
771                 /* Change the core_if's lock to hcd/pcd lock depend on mode? */
772 #ifndef DWC_HOST_ONLY
773                 if (gpwrdn_temp.b.idsts)
774                         core_if->lock = otg_dev->pcd->lock;
775 #endif
776 #ifndef DWC_DEVICE_ONLY
777                 if (!gpwrdn_temp.b.idsts) {
778                         core_if->lock = otg_dev->hcd->lock;
779                         is_host = 1;
780                 }
781 #endif
782                 DWC_PRINTF("RESTART ADP\n");
783                 if (core_if->adp.probe_enabled)
784                         dwc_otg_adp_probe_stop(core_if);
785                 if (core_if->adp.sense_enabled)
786                         dwc_otg_adp_sense_stop(core_if);
787                 if (core_if->adp.sense_timer_started)
788                         DWC_TIMER_CANCEL(core_if->adp.sense_timer);
789                 if (core_if->adp.vbuson_timer_started)
790                         DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
791                 core_if->adp.probe_timer_values[0] = -1;
792                 core_if->adp.probe_timer_values[1] = -1;
793                 core_if->adp.sense_timer_started = 0;
794                 core_if->adp.vbuson_timer_started = 0;
795                 core_if->adp.probe_counter = 0;
796                 core_if->adp.gpwrdn = 0;
797
798                 /* Disable PMU and restart ADP */
799                 gpwrdn_temp.d32 = 0;
800                 gpwrdn_temp.b.pmuactv = 1;
801                 gpwrdn_temp.b.pmuintsel = 1;
802                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
803                                  0);
804                 DWC_PRINTF("Check point 1\n");
805                 dwc_mdelay(110);
806                 dwc_otg_adp_start(core_if, is_host);
807                 DWC_SPINLOCK(core_if->lock);
808         }
809
810         return 1;
811 }
812
813 static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t *core_if)
814 {
815         gpwrdn_data_t gpwrdn = {.d32 = 0 };
816         int32_t otg_cap_param = core_if->core_params->otg_cap;
817         DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
818
819         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
820         if (core_if->power_down == 2) {
821                 if (!core_if->hibernation_suspend) {
822                         DWC_PRINTF("Already exited from Hibernation\n");
823                         return 1;
824                 }
825
826                 if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
827                      otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
828                     gpwrdn.b.bsessvld == 0) {
829                         /* Save gpwrdn register for further usage if stschng interrupt */
830                         core_if->gr_backup->gpwrdn_local =
831                             DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
832                         /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
833                         return 1;
834                 }
835
836                 /* Switch on the voltage to the core */
837                 gpwrdn.d32 = 0;
838                 gpwrdn.b.pwrdnswtch = 1;
839                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
840                                  0);
841                 dwc_udelay(10);
842
843                 /* Reset the core */
844                 gpwrdn.d32 = 0;
845                 gpwrdn.b.pwrdnrstn = 1;
846                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
847                                  0);
848                 dwc_udelay(10);
849
850                 /* Disable power clamps */
851                 gpwrdn.d32 = 0;
852                 gpwrdn.b.pwrdnclmp = 1;
853                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
854                                  0);
855
856                 /* Remove reset the core signal */
857                 gpwrdn.d32 = 0;
858                 gpwrdn.b.pwrdnrstn = 1;
859                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
860                                  gpwrdn.d32);
861                 dwc_udelay(10);
862
863                 /* Disable PMU interrupt */
864                 gpwrdn.d32 = 0;
865                 gpwrdn.b.pmuintsel = 1;
866                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
867                                  0);
868                 dwc_udelay(10);
869
870                 /*Indicates that we are exiting from hibernation */
871                 core_if->hibernation_suspend = 0;
872
873                 /* Disable PMU */
874                 gpwrdn.d32 = 0;
875                 gpwrdn.b.pmuactv = 1;
876                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
877                                  0);
878                 dwc_udelay(10);
879
880                 core_if->op_state = B_PERIPHERAL;
881                 dwc_otg_core_init(core_if);
882                 dwc_otg_enable_global_interrupts(core_if);
883                 cil_pcd_start(core_if);
884
885                 if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
886                     otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
887                         /*
888                          * Initiate SRP after initial ADP probe.
889                          */
890                         dwc_otg_initiate_srp(core_if);
891                 }
892         } else if (core_if->adp_enable) {
893                 dwc_otg_adp_probe_stop(core_if);
894                 if (DWC_WORKQ_PENDING(core_if->wq_otg))
895                         core_if->stop_adpprb = 1;
896                 /* Disable Power Down Logic */
897                 gpwrdn.d32 = 0;
898                 gpwrdn.b.pmuintsel = 1;
899                 gpwrdn.b.pmuactv = 1;
900                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
901                                  0);
902
903                 /*
904                  * Initialize the Core for Device mode.
905                  */
906                 core_if->op_state = B_PERIPHERAL;
907                 cil_pcd_start(core_if);
908                 dwc_otg_enable_global_interrupts(core_if);
909         }
910
911         return 1;
912 }
913
914 /**
915  * This interrupt indicates that the Wakeup Logic has detected a
916  * status change either on IDDIG or BSessVld.
917  */
918 static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
919 {
920         int retval;
921         gpwrdn_data_t gpwrdn = {.d32 = 0 };
922         gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
923         dwc_otg_core_if_t *core_if = otg_dev->core_if;
924
925         DWC_PRINTF("%s called\n", __FUNCTION__);
926
927         if (core_if->power_down == 2) {
928                 if (core_if->hibernation_suspend <= 0) {
929                         DWC_PRINTF("Already exited from Hibernation\n");
930                         return 1;
931                 } else
932                         gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
933
934         } else {
935                 gpwrdn_temp.d32 = core_if->adp.gpwrdn;
936         }
937
938         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
939
940         if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
941                 retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
942         } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
943                 retval = dwc_otg_handle_pwrdn_session_change(core_if);
944         }
945
946         return retval;
947 }
948
949 /**
950  * This interrupt indicates that the Wakeup Logic has detected a
951  * SRP.
952  */
953 static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t *core_if)
954 {
955         gpwrdn_data_t gpwrdn = {.d32 = 0 };
956
957         DWC_PRINTF("%s called\n", __FUNCTION__);
958
959         if (!core_if->hibernation_suspend) {
960                 DWC_PRINTF("Already exited from Hibernation\n");
961                 return 1;
962         }
963 #ifdef DWC_DEV_SRPCAP
964         if (core_if->pwron_timer_started) {
965                 core_if->pwron_timer_started = 0;
966                 DWC_TIMER_CANCEL(core_if->pwron_timer);
967         }
968 #endif
969
970         /* Switch on the voltage to the core */
971         gpwrdn.b.pwrdnswtch = 1;
972         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
973         dwc_udelay(10);
974
975         /* Reset the core */
976         gpwrdn.d32 = 0;
977         gpwrdn.b.pwrdnrstn = 1;
978         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
979         dwc_udelay(10);
980
981         /* Disable power clamps */
982         gpwrdn.d32 = 0;
983         gpwrdn.b.pwrdnclmp = 1;
984         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
985
986         /* Remove reset the core signal */
987         gpwrdn.d32 = 0;
988         gpwrdn.b.pwrdnrstn = 1;
989         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
990         dwc_udelay(10);
991
992         /* Disable PMU interrupt */
993         gpwrdn.d32 = 0;
994         gpwrdn.b.pmuintsel = 1;
995         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
996
997         /* Indicates that we are exiting from hibernation */
998         core_if->hibernation_suspend = 0;
999
1000         /* Disable PMU */
1001         gpwrdn.d32 = 0;
1002         gpwrdn.b.pmuactv = 1;
1003         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
1004         dwc_udelay(10);
1005
1006         /* Programm Disable VBUS to 0 */
1007         gpwrdn.d32 = 0;
1008         gpwrdn.b.dis_vbus = 1;
1009         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
1010
1011         /*Initialize the core as Host */
1012         core_if->op_state = A_HOST;
1013         dwc_otg_core_init(core_if);
1014         dwc_otg_enable_global_interrupts(core_if);
1015         cil_hcd_start(core_if);
1016
1017         return 1;
1018 }
1019
1020 /** This interrupt indicates that restore command after Hibernation
1021  * was completed by the core. */
1022 int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t *core_if)
1023 {
1024         pcgcctl_data_t pcgcctl;
1025         DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
1026
1027         /* TODO De-assert restore signal. 8.a */
1028         pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
1029         if (pcgcctl.b.restoremode == 1) {
1030                 gintmsk_data_t gintmsk = {.d32 = 0 };
1031                 /*
1032                  * If restore mode is Remote Wakeup,
1033                  * unmask Remote Wakeup interrupt.
1034                  */
1035                 gintmsk.b.wkupintr = 1;
1036                 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
1037                                  0, gintmsk.d32);
1038         }
1039
1040         return 1;
1041 }
1042
1043 /**
1044  * This interrupt indicates that a device has been disconnected from
1045  * the root port.
1046  */
1047 int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t *core_if)
1048 {
1049         gintsts_data_t gintsts;
1050
1051         DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
1052                     (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
1053                     op_state_str(core_if));
1054
1055 /** @todo Consolidate this if statement. */
1056 #ifndef DWC_HOST_ONLY
1057         if (core_if->op_state == B_HOST) {
1058                 /* If in device mode Disconnect and stop the HCD, then
1059                  * start the PCD. */
1060                 DWC_SPINUNLOCK(core_if->lock);
1061                 cil_hcd_disconnect(core_if);
1062                 cil_pcd_start(core_if);
1063                 DWC_SPINLOCK(core_if->lock);
1064                 core_if->op_state = B_PERIPHERAL;
1065         } else if (dwc_otg_is_device_mode(core_if)) {
1066                 gotgctl_data_t gotgctl = {.d32 = 0 };
1067                 gotgctl.d32 =
1068                     DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
1069                 if (gotgctl.b.hstsethnpen == 1) {
1070                         /* Do nothing, if HNP in process the OTG
1071                          * interrupt "Host Negotiation Detected"
1072                          * interrupt will do the mode switch.
1073                          */
1074                 } else if (gotgctl.b.devhnpen == 0) {
1075                         /* If in device mode Disconnect and stop the HCD, then
1076                          * start the PCD. */
1077                         DWC_SPINUNLOCK(core_if->lock);
1078                         cil_hcd_disconnect(core_if);
1079                         cil_pcd_start(core_if);
1080                         DWC_SPINLOCK(core_if->lock);
1081                         core_if->op_state = B_PERIPHERAL;
1082                 } else {
1083                         DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
1084                 }
1085         } else {
1086                 if (core_if->op_state == A_HOST) {
1087                         /* A-Cable still connected but device disconnected. */
1088                         cil_hcd_disconnect(core_if);
1089                         if (core_if->adp_enable) {
1090                                 gpwrdn_data_t gpwrdn = {.d32 = 0 };
1091                                 cil_hcd_stop(core_if);
1092                                 /* Enable Power Down Logic */
1093                                 gpwrdn.b.pmuintsel = 1;
1094                                 gpwrdn.b.pmuactv = 1;
1095                                 DWC_MODIFY_REG32(&core_if->
1096                                                  core_global_regs->gpwrdn, 0,
1097                                                  gpwrdn.d32);
1098                                 dwc_otg_adp_probe_start(core_if);
1099
1100                                 /* Power off the core */
1101                                 if (core_if->power_down == 2) {
1102                                         gpwrdn.d32 = 0;
1103                                         gpwrdn.b.pwrdnswtch = 1;
1104                                         DWC_MODIFY_REG32
1105                                             (&core_if->core_global_regs->gpwrdn,
1106                                              gpwrdn.d32, 0);
1107                                 }
1108                         }
1109                 }
1110         }
1111 #endif
1112         /* Change to L3(OFF) state */
1113         core_if->lx_state = DWC_OTG_L3;
1114
1115         gintsts.d32 = 0;
1116         gintsts.b.disconnect = 1;
1117         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
1118         return 1;
1119 }
1120
1121 /**
1122  * This interrupt indicates that SUSPEND state has been detected on
1123  * the USB.
1124  *
1125  * For HNP the USB Suspend interrupt signals the change from
1126  * "a_peripheral" to "a_host".
1127  *
1128  * When power management is enabled the core will be put in low power
1129  * mode.
1130  */
1131 int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t *core_if)
1132 {
1133         dsts_data_t dsts;
1134         gintsts_data_t gintsts;
1135         dcfg_data_t dcfg;
1136
1137         DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
1138
1139         if ((core_if->otg_ver == 1) && (core_if->op_state == A_PERIPHERAL))
1140                 dwc_mdelay(200);        /* vahrama - WA - see BU's mail */
1141
1142         if (dwc_otg_is_device_mode(core_if)) {
1143                 /* Check the Device status register to determine if the Suspend
1144                  * state is active. */
1145                 dsts.d32 =
1146                     DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
1147                 DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
1148                 DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
1149                             "HWCFG4.power Optimize=%d\n",
1150                             dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
1151
1152 #ifdef PARTIAL_POWER_DOWN
1153 /** @todo Add a module parameter for power management. */
1154
1155                 if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
1156                         pcgcctl_data_t power = {.d32 = 0 };
1157                         DWC_DEBUGPL(DBG_CIL, "suspend\n");
1158
1159                         power.b.pwrclmp = 1;
1160                         DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
1161
1162                         power.b.rstpdwnmodule = 1;
1163                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
1164
1165                         power.b.stoppclk = 1;
1166                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
1167
1168                 } else {
1169                         DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
1170                 }
1171 #endif
1172                 /* PCD callback for suspend. Release the lock inside of callback function */
1173                 cil_pcd_suspend(core_if);
1174                 if (core_if->power_down == 2) {
1175                         dcfg.d32 =
1176                             DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
1177                                            dcfg);
1178                         DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",
1179                                     core_if->lx_state);
1180                         DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",
1181                                     dcfg.b.devaddr);
1182
1183                         if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
1184                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
1185                                 gpwrdn_data_t gpwrdn = {.d32 = 0 };
1186                                 gusbcfg_data_t gusbcfg = {.d32 = 0 };
1187
1188                                 /* Change to L2(suspend) state */
1189                                 core_if->lx_state = DWC_OTG_L2;
1190
1191                                 /* Clear interrupt in gintsts */
1192                                 gintsts.d32 = 0;
1193                                 gintsts.b.usbsuspend = 1;
1194                                 DWC_WRITE_REG32(&core_if->
1195                                                 core_global_regs->gintsts,
1196                                                 gintsts.d32);
1197                                 DWC_PRINTF("Start of hibernation completed\n");
1198                                 dwc_otg_save_global_regs(core_if);
1199                                 dwc_otg_save_dev_regs(core_if);
1200
1201                                 gusbcfg.d32 =
1202                                     DWC_READ_REG32(&core_if->
1203                                                    core_global_regs->gusbcfg);
1204                                 if (gusbcfg.b.ulpi_utmi_sel == 1) {
1205                                         /* ULPI interface */
1206                                         /* Suspend the Phy Clock */
1207                                         pcgcctl.d32 = 0;
1208                                         pcgcctl.b.stoppclk = 1;
1209                                         DWC_MODIFY_REG32(core_if->pcgcctl, 0,
1210                                                          pcgcctl.d32);
1211                                         dwc_udelay(10);
1212                                         gpwrdn.b.pmuactv = 1;
1213                                         DWC_MODIFY_REG32
1214                                             (&core_if->core_global_regs->gpwrdn,
1215                                              0, gpwrdn.d32);
1216                                 } else {
1217                                         /* UTMI+ Interface */
1218                                         gpwrdn.b.pmuactv = 1;
1219                                         DWC_MODIFY_REG32
1220                                             (&core_if->core_global_regs->gpwrdn,
1221                                              0, gpwrdn.d32);
1222                                         dwc_udelay(10);
1223                                         pcgcctl.b.stoppclk = 1;
1224                                         DWC_MODIFY_REG32(core_if->pcgcctl, 0,
1225                                                          pcgcctl.d32);
1226                                         dwc_udelay(10);
1227                                 }
1228
1229                                 /* Set flag to indicate that we are in hibernation */
1230                                 core_if->hibernation_suspend = 1;
1231                                 /* Enable interrupts from wake up logic */
1232                                 gpwrdn.d32 = 0;
1233                                 gpwrdn.b.pmuintsel = 1;
1234                                 DWC_MODIFY_REG32(&core_if->
1235                                                  core_global_regs->gpwrdn, 0,
1236                                                  gpwrdn.d32);
1237                                 dwc_udelay(10);
1238
1239                                 /* Unmask device mode interrupts in GPWRDN */
1240                                 gpwrdn.d32 = 0;
1241                                 gpwrdn.b.rst_det_msk = 1;
1242                                 gpwrdn.b.lnstchng_msk = 1;
1243                                 gpwrdn.b.sts_chngint_msk = 1;
1244                                 DWC_MODIFY_REG32(&core_if->
1245                                                  core_global_regs->gpwrdn, 0,
1246                                                  gpwrdn.d32);
1247                                 dwc_udelay(10);
1248
1249                                 /* Enable Power Down Clamp */
1250                                 gpwrdn.d32 = 0;
1251                                 gpwrdn.b.pwrdnclmp = 1;
1252                                 DWC_MODIFY_REG32(&core_if->
1253                                                  core_global_regs->gpwrdn, 0,
1254                                                  gpwrdn.d32);
1255                                 dwc_udelay(10);
1256
1257                                 /* Switch off VDD */
1258                                 gpwrdn.d32 = 0;
1259                                 gpwrdn.b.pwrdnswtch = 1;
1260                                 DWC_MODIFY_REG32(&core_if->
1261                                                  core_global_regs->gpwrdn, 0,
1262                                                  gpwrdn.d32);
1263
1264                                 /* Save gpwrdn register for further usage if stschng interrupt */
1265                                 core_if->gr_backup->gpwrdn_local =
1266                                     DWC_READ_REG32(&core_if->core_global_regs->
1267                                                    gpwrdn);
1268                                 DWC_PRINTF("Hibernation completed\n");
1269
1270                                 return 1;
1271                         }
1272                 } else if (core_if->power_down == 3) {
1273                         pcgcctl_data_t pcgcctl = {.d32 = 0 };
1274                         dcfg.d32 =
1275                             DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
1276                                            dcfg);
1277                         DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",
1278                                     core_if->lx_state);
1279                         DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",
1280                                     dcfg.b.devaddr);
1281
1282                         if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
1283                                 DWC_DEBUGPL(DBG_ANY,
1284                                             "Start entering to extended hibernation\n");
1285                                 core_if->xhib = 1;
1286
1287                                 /* Clear interrupt in gintsts */
1288                                 gintsts.d32 = 0;
1289                                 gintsts.b.usbsuspend = 1;
1290                                 DWC_WRITE_REG32(&core_if->
1291                                                 core_global_regs->gintsts,
1292                                                 gintsts.d32);
1293
1294                                 dwc_otg_save_global_regs(core_if);
1295                                 dwc_otg_save_dev_regs(core_if);
1296
1297                                 /* Wait for 10 PHY clocks */
1298                                 dwc_udelay(10);
1299
1300                                 /* Program GPIO register while entering to xHib */
1301                                 DWC_WRITE_REG32(&core_if->core_global_regs->
1302                                                 ggpio, 0x1);
1303
1304                                 pcgcctl.b.enbl_extnd_hiber = 1;
1305                                 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
1306                                                  pcgcctl.d32);
1307                                 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
1308                                                  pcgcctl.d32);
1309
1310                                 pcgcctl.d32 = 0;
1311                                 pcgcctl.b.extnd_hiber_pwrclmp = 1;
1312                                 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
1313                                                  pcgcctl.d32);
1314
1315                                 pcgcctl.d32 = 0;
1316                                 pcgcctl.b.extnd_hiber_switch = 1;
1317                                 core_if->gr_backup->xhib_gpwrdn =
1318                                     DWC_READ_REG32(&core_if->core_global_regs->
1319                                                    gpwrdn);
1320                                 core_if->gr_backup->xhib_pcgcctl =
1321                                     DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.
1322                                     d32;
1323                                 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
1324                                                  pcgcctl.d32);
1325
1326                                 DWC_DEBUGPL(DBG_ANY,
1327                                             "Finished entering to extended hibernation\n");
1328
1329                                 return 1;
1330                         }
1331                 }
1332                 if ((core_if->otg_ver == 1)
1333                     && (core_if->core_params->otg_cap ==
1334                         DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)) {
1335                         gotgctl_data_t gotgctl = {.d32 = 0 };
1336                         gotgctl.d32 =
1337                             DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
1338                         if (gotgctl.b.devhnpen && core_if->otg_ver == 1) {
1339                                 gotgctl_data_t gotgctl = {.d32 = 0 };
1340                                 dwc_mdelay(5);
1341                                 /**@todo Is the gotgctl.devhnpen cleared
1342                                  * by a USB Reset? */
1343                                 gotgctl.b.devhnpen = 1;
1344                                 gotgctl.b.hnpreq = 1;
1345                                 DWC_WRITE_REG32(&core_if->core_global_regs->
1346                                                 gotgctl, gotgctl.d32);
1347                         }
1348                 }
1349         } else {
1350                 if (core_if->op_state == A_PERIPHERAL) {
1351                         DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
1352                         /* Clear the a_peripheral flag, back to a_host. */
1353                         DWC_SPINUNLOCK(core_if->lock);
1354                         cil_pcd_stop(core_if);
1355                         cil_hcd_start(core_if);
1356                         DWC_SPINLOCK(core_if->lock);
1357                         core_if->op_state = A_HOST;
1358                 }
1359         }
1360
1361         /* Change to L2(suspend) state */
1362         core_if->lx_state = DWC_OTG_L2;
1363
1364         /* Clear interrupt */
1365         gintsts.d32 = 0;
1366         gintsts.b.usbsuspend = 1;
1367         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
1368
1369         return 1;
1370 }
1371
1372 static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t *core_if)
1373 {
1374         gpwrdn_data_t gpwrdn = {.d32 = 0 };
1375         pcgcctl_data_t pcgcctl = {.d32 = 0 };
1376         gahbcfg_data_t gahbcfg = {.d32 = 0 };
1377
1378         dwc_udelay(10);
1379
1380         /* Program GPIO register while entering to xHib */
1381         DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
1382
1383         pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
1384         pcgcctl.b.extnd_hiber_pwrclmp = 0;
1385         DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
1386         dwc_udelay(10);
1387
1388         gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
1389         gpwrdn.b.restore = 1;
1390         DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
1391         dwc_udelay(10);
1392
1393         restore_lpm_i2c_regs(core_if);
1394
1395         pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
1396         pcgcctl.b.max_xcvrselect = 1;
1397         pcgcctl.b.ess_reg_restored = 0;
1398         pcgcctl.b.extnd_hiber_switch = 0;
1399         pcgcctl.b.extnd_hiber_pwrclmp = 0;
1400         pcgcctl.b.enbl_extnd_hiber = 1;
1401         DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
1402
1403         gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
1404         gahbcfg.b.glblintrmsk = 1;
1405         DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
1406
1407         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
1408         DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
1409
1410         DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
1411                         core_if->gr_backup->gusbcfg_local);
1412         DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
1413                         core_if->dr_backup->dcfg);
1414
1415         pcgcctl.d32 = 0;
1416         pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
1417         pcgcctl.b.max_xcvrselect = 1;
1418         pcgcctl.d32 |= 0x608;
1419         DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
1420         dwc_udelay(10);
1421
1422         pcgcctl.d32 = 0;
1423         pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
1424         pcgcctl.b.max_xcvrselect = 1;
1425         pcgcctl.b.ess_reg_restored = 1;
1426         pcgcctl.b.enbl_extnd_hiber = 1;
1427         pcgcctl.b.rstpdwnmodule = 1;
1428         pcgcctl.b.restoremode = 1;
1429         DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
1430
1431         DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
1432
1433         return 1;
1434 }
1435
1436 #ifdef CONFIG_USB_DWC_OTG_LPM
1437 /**
1438  * This function hadles LPM transaction received interrupt.
1439  */
1440 static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t *core_if)
1441 {
1442         glpmcfg_data_t lpmcfg;
1443         gintsts_data_t gintsts;
1444
1445         if (!core_if->core_params->lpm_enable) {
1446                 DWC_PRINTF("Unexpected LPM interrupt\n");
1447         }
1448
1449         lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
1450         DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
1451
1452         if (dwc_otg_is_host_mode(core_if)) {
1453                 cil_hcd_sleep(core_if);
1454         } else {
1455
1456                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
1457
1458                 lpmcfg.b.hird_thres |= (1 << 4);
1459                 lpmcfg.b.en_utmi_sleep = 1;
1460
1461                 pcgcctl.b.enbl_sleep_gating = 1;
1462                 DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
1463
1464                 if (dwc_otg_get_param_besl_enable(core_if)) {
1465                         lpmcfg.b.en_besl = 1;
1466                 }
1467
1468                 DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
1469                                 lpmcfg.d32);
1470         }
1471
1472         /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
1473         dwc_udelay(10);
1474         lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
1475         if (lpmcfg.b.prt_sleep_sts) {
1476                 /* Save the current state */
1477                 core_if->lx_state = DWC_OTG_L1;
1478         }
1479
1480         /* Clear interrupt  */
1481         gintsts.d32 = 0;
1482         gintsts.b.lpmtranrcvd = 1;
1483         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
1484         return 1;
1485 }
1486 #endif /* CONFIG_USB_DWC_OTG_LPM */
1487
1488 /**
1489  * This function returns the Core Interrupt register.
1490  */
1491 static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t *core_if)
1492 {
1493         uint32_t retval;
1494
1495         gahbcfg_data_t gahbcfg = {.d32 = 0 };
1496         gintsts_data_t gintsts;
1497         gintmsk_data_t gintmsk;
1498         gintmsk_data_t gintmsk_common = {.d32 = 0 };
1499         gintmsk_common.b.wkupintr = 1;
1500         gintmsk_common.b.sessreqintr = 1;
1501         gintmsk_common.b.conidstschng = 1;
1502         gintmsk_common.b.otgintr = 1;
1503         gintmsk_common.b.modemismatch = 1;
1504         gintmsk_common.b.disconnect = 1;
1505         gintmsk_common.b.usbsuspend = 1;
1506 #ifdef CONFIG_USB_DWC_OTG_LPM
1507         gintmsk_common.b.lpmtranrcvd = 1;
1508 #endif
1509         gintmsk_common.b.restoredone = 1;
1510         /** @todo: The port interrupt occurs while in device
1511          * mode. Added code to CIL to clear the interrupt for now!
1512          */
1513         gintmsk_common.b.portintr = 1;
1514
1515         gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
1516         gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
1517         gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
1518
1519 #ifdef DEBUG
1520         /* if any common interrupts set */
1521         if (gintsts.d32 & gintmsk_common.d32) {
1522                 DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
1523                             gintsts.d32, gintmsk.d32);
1524         }
1525 #endif
1526         if (gahbcfg.b.glblintrmsk) {
1527                 retval = (gintsts.d32 & gintmsk.d32) & gintmsk_common.d32;
1528                 return retval;
1529         } else {
1530                 return 0;
1531         }
1532 }
1533
1534 /* MACRO for clearing interupt bits in GPWRDN register */
1535 #define CLEAR_GPWRDN_INTR(__core_if, __intr) \
1536 do { \
1537                 gpwrdn_data_t gpwrdn = {.d32 = 0}; \
1538                 gpwrdn.b.__intr = 1; \
1539                 DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
1540                 0, gpwrdn.d32); \
1541 } while (0)
1542
1543 /**
1544  * Common interrupt handler.
1545  *
1546  * The common interrupts are those that occur in both Host and Device mode.
1547  * This handler handles the following interrupts:
1548  * - Mode Mismatch Interrupt
1549  * - Disconnect Interrupt
1550  * - OTG Interrupt
1551  * - Connector ID Status Change Interrupt
1552  * - Session Request Interrupt.
1553  * - Resume / Remote Wakeup Detected Interrupt.
1554  * - LPM Transaction Received Interrupt
1555  * - ADP Transaction Received Interrupt
1556  *
1557  */
1558 int32_t dwc_otg_handle_common_intr(void *dev)
1559 {
1560         int retval = 0;
1561         gintsts_data_t gintsts;
1562         gpwrdn_data_t gpwrdn = {.d32 = 0 };
1563         dwc_otg_device_t *otg_dev = dev;
1564         dwc_otg_core_if_t *core_if = otg_dev->core_if;
1565         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
1566
1567         if (dwc_otg_check_haps_status(core_if) == -1) {
1568                 DWC_WARN("HAPS is disconnected");
1569                 return retval;
1570         }
1571
1572         if (dwc_otg_is_device_mode(core_if))
1573                 core_if->frame_num = dwc_otg_get_frame_number(core_if);
1574
1575         if (core_if->lock)
1576                 DWC_SPINLOCK(core_if->lock);
1577
1578         if (core_if->power_down == 3 && core_if->xhib == 1) {
1579                 DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
1580                 retval |= dwc_otg_handle_xhib_exit_intr(core_if);
1581                 core_if->xhib = 2;
1582                 if (core_if->lock)
1583                         DWC_SPINUNLOCK(core_if->lock);
1584
1585                 return retval;
1586         }
1587
1588         if (core_if->hibernation_suspend <= 0) {
1589                 gintsts.d32 = dwc_otg_read_common_intr(core_if);
1590
1591                 if (gintsts.b.modemismatch) {
1592                         retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
1593                 }
1594                 if (gintsts.b.otgintr) {
1595                         retval |= dwc_otg_handle_otg_intr(core_if);
1596                 }
1597                 if (gintsts.b.conidstschng) {
1598                         retval |=
1599                             dwc_otg_handle_conn_id_status_change_intr(core_if);
1600                 }
1601                 if (gintsts.b.disconnect) {
1602                         retval |= dwc_otg_handle_disconnect_intr(core_if);
1603                 }
1604                 if (gintsts.b.sessreqintr) {
1605                         retval |= dwc_otg_handle_session_req_intr(core_if);
1606                 }
1607                 if (gintsts.b.wkupintr) {
1608                         retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
1609                 }
1610                 if (gintsts.b.usbsuspend) {
1611                         retval |= dwc_otg_handle_usb_suspend_intr(core_if);
1612                 }
1613 #ifdef CONFIG_USB_DWC_OTG_LPM
1614                 if (gintsts.b.lpmtranrcvd) {
1615                         retval |= dwc_otg_handle_lpm_intr(core_if);
1616                 }
1617 #endif
1618                 if (gintsts.b.restoredone) {
1619                         gintsts.d32 = 0;
1620                         if (core_if->power_down == 2)
1621                                 core_if->hibernation_suspend = -1;
1622                         else if (core_if->power_down == 3 && core_if->xhib == 2) {
1623                                 gpwrdn_data_t gpwrdn = {.d32 = 0 };
1624                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
1625                                 dctl_data_t dctl = {.d32 = 0 };
1626
1627                                 DWC_WRITE_REG32(&core_if->
1628                                                 core_global_regs->gintsts,
1629                                                 0xFFFFFFFF);
1630
1631                                 DWC_DEBUGPL(DBG_ANY,
1632                                             "RESTORE DONE generated\n");
1633
1634                                 gpwrdn.b.restore = 1;
1635                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
1636                                                  gpwrdn, gpwrdn.d32, 0);
1637                                 dwc_udelay(10);
1638
1639                                 pcgcctl.b.rstpdwnmodule = 1;
1640                                 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
1641                                                  0);
1642
1643                                 DWC_WRITE_REG32(&core_if->core_global_regs->
1644                                                 gusbcfg,
1645                                                 core_if->gr_backup->
1646                                                 gusbcfg_local);
1647                                 DWC_WRITE_REG32(&core_if->dev_if->
1648                                                 dev_global_regs->dcfg,
1649                                                 core_if->dr_backup->dcfg);
1650                                 DWC_WRITE_REG32(&core_if->dev_if->
1651                                                 dev_global_regs->dctl,
1652                                                 core_if->dr_backup->dctl);
1653                                 dwc_udelay(50);
1654
1655                                 dctl.b.pwronprgdone = 1;
1656                                 DWC_MODIFY_REG32(&core_if->dev_if->
1657                                                  dev_global_regs->dctl, 0,
1658                                                  dctl.d32);
1659                                 dwc_udelay(10);
1660
1661                                 dwc_otg_restore_global_regs(core_if);
1662                                 dwc_otg_restore_dev_regs(core_if, 0);
1663
1664                                 dctl.d32 = 0;
1665                                 dctl.b.pwronprgdone = 1;
1666                                 DWC_MODIFY_REG32(&core_if->dev_if->
1667                                                  dev_global_regs->dctl,
1668                                                  dctl.d32, 0);
1669                                 dwc_udelay(10);
1670
1671                                 pcgcctl.d32 = 0;
1672                                 pcgcctl.b.enbl_extnd_hiber = 1;
1673                                 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
1674                                                  0);
1675
1676                                 /* The core will be in ON STATE */
1677                                 core_if->lx_state = DWC_OTG_L0;
1678                                 core_if->xhib = 0;
1679
1680                                 DWC_SPINUNLOCK(core_if->lock);
1681                                 if (core_if->pcd_cb
1682                                     && core_if->pcd_cb->resume_wakeup) {
1683                                         core_if->pcd_cb->resume_wakeup(core_if->
1684                                                                        pcd_cb->
1685                                                                        p);
1686                                 }
1687                                 DWC_SPINLOCK(core_if->lock);
1688
1689                         }
1690
1691                         gintsts.b.restoredone = 1;
1692                         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,
1693                                         gintsts.d32);
1694                         DWC_PRINTF(" --Restore done interrupt received-- \n");
1695                         retval |= 1;
1696                 }
1697                 if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
1698                         /* The port interrupt occurs while in device mode with HPRT0
1699                          * Port Enable/Disable.
1700                          */
1701                         gintsts.d32 = 0;
1702                         gintsts.b.portintr = 1;
1703                         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,
1704                                         gintsts.d32);
1705                         retval |= 1;
1706
1707                 }
1708         } else {
1709                 DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
1710
1711                 if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
1712                         CLEAR_GPWRDN_INTR(core_if, disconn_det);
1713                         if (gpwrdn.b.linestate == 0) {
1714                                 dwc_otg_handle_pwrdn_disconnect_intr(core_if);
1715                         } else {
1716                                 DWC_PRINTF
1717                                     ("Disconnect detected while linestate is not 0\n");
1718                         }
1719
1720                         retval |= 1;
1721                 }
1722                 if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
1723                         CLEAR_GPWRDN_INTR(core_if, lnstschng);
1724                         /* remote wakeup from hibernation */
1725                         if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
1726                                 dwc_otg_handle_pwrdn_wakeup_detected_intr
1727                                     (core_if);
1728                         } else {
1729                                 DWC_PRINTF("gpwrdn.linestate = %d\n",
1730                                            gpwrdn.b.linestate);
1731                         }
1732                         retval |= 1;
1733                 }
1734                 if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
1735                         CLEAR_GPWRDN_INTR(core_if, rst_det);
1736                         if (gpwrdn.b.linestate == 0) {
1737                                 DWC_PRINTF("Reset detected\n");
1738                                 retval |=
1739                                     dwc_otg_device_hibernation_restore(core_if,
1740                                                                        0, 1);
1741                         }
1742                 }
1743                 if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
1744                         CLEAR_GPWRDN_INTR(core_if, srp_det);
1745                         dwc_otg_handle_pwrdn_srp_intr(core_if);
1746                         retval |= 1;
1747                 }
1748         }
1749         /* Handle ADP interrupt here */
1750         if (gpwrdn.b.adp_int) {
1751                 DWC_PRINTF("ADP interrupt\n");
1752                 CLEAR_GPWRDN_INTR(core_if, adp_int);
1753                 dwc_otg_adp_handle_intr(core_if);
1754                 retval |= 1;
1755         }
1756         if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
1757                 DWC_PRINTF("STS CHNG interrupt asserted\n");
1758                 CLEAR_GPWRDN_INTR(core_if, sts_chngint);
1759                 dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
1760
1761                 retval |= 1;
1762         }
1763         if (core_if->lock)
1764                 DWC_SPINUNLOCK(core_if->lock);
1765
1766         return retval;
1767 }