rk3036: usb: add support of wakeup by GRF linestate change
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / dwc_otg_adp.c
1 /* ==========================================================================
2  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
3  * $Revision: #13 $
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 #include "common_port/dwc_os.h"
35 #include "dwc_otg_regs.h"
36 #include "dwc_otg_cil.h"
37 #include "dwc_otg_adp.h"
38
39 /** @file
40  *
41  * This file contains the most of the Attach Detect Protocol implementation for
42  * the driver to support OTG Rev2.0.
43  *
44  */
45
46 void dwc_otg_adp_write_reg(dwc_otg_core_if_t *core_if, uint32_t value)
47 {
48         adpctl_data_t adpctl;
49
50         adpctl.d32 = value;
51         adpctl.b.ar = 0x2;
52
53         DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
54
55         while (adpctl.b.ar)
56                 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
57
58 }
59
60 /**
61  * Function is called to read ADP registers
62  */
63 uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t *core_if)
64 {
65         adpctl_data_t adpctl;
66
67         adpctl.d32 = 0;
68         adpctl.b.ar = 0x1;
69
70         DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
71
72         while (adpctl.b.ar)
73                 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
74
75         return adpctl.d32;
76 }
77
78 /**
79  * Function is called to read ADPCTL register and filter Write-clear bits
80  */
81 uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t *core_if)
82 {
83         adpctl_data_t adpctl;
84
85         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
86         adpctl.b.adp_tmout_int = 0;
87         adpctl.b.adp_prb_int = 0;
88         adpctl.b.adp_tmout_int = 0;
89
90         return adpctl.d32;
91 }
92
93 /**
94  * Function is called to write ADP registers
95  */
96 void dwc_otg_adp_modify_reg(dwc_otg_core_if_t *core_if, uint32_t clr,
97                             uint32_t set)
98 {
99         dwc_otg_adp_write_reg(core_if,
100                               (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
101 }
102
103 static void adp_probe_func(void *ptr)
104 {
105         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
106         dwc_otg_adp_probe_start(core_if);
107 }
108
109 static void adp_sense_timeout(void *ptr)
110 {
111         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
112         core_if->adp.sense_timer_started = 0;
113         DWC_PRINTF("ADP SENSE TIMEOUT\n");
114         if (core_if->adp_enable) {
115                 dwc_otg_adp_sense_stop(core_if);
116                 DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, adp_probe_func,
117                                            core_if, 2500, "start probe");
118         }
119 }
120
121 /**
122  * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
123  */
124 static void adp_vbuson_timeout(void *ptr)
125 {
126         gpwrdn_data_t gpwrdn;
127         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
128         hprt0_data_t hprt0 = {.d32 = 0 };
129         pcgcctl_data_t pcgcctl = {.d32 = 0 };
130         DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",
131                    __func__);
132         if (core_if) {
133                 core_if->adp.vbuson_timer_started = 0;
134                 /* Turn off vbus */
135                 hprt0.b.prtpwr = 1;
136                 DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
137                 gpwrdn.d32 = 0;
138
139                 /* Power off the core */
140                 if (core_if->power_down == 2) {
141                         /* Enable Wakeup Logic */
142                         /* gpwrdn.b.wkupactiv = 1; */
143                         gpwrdn.b.pmuactv = 0;
144                         gpwrdn.b.pwrdnrstn = 1;
145                         gpwrdn.b.pwrdnclmp = 1;
146                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
147                                          gpwrdn.d32);
148
149                         /* Suspend the Phy Clock */
150                         pcgcctl.b.stoppclk = 1;
151                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
152
153                         /* Switch on VDD */
154                         /* gpwrdn.b.wkupactiv = 1; */
155                         gpwrdn.b.pmuactv = 1;
156                         gpwrdn.b.pwrdnrstn = 1;
157                         gpwrdn.b.pwrdnclmp = 1;
158                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
159                                          gpwrdn.d32);
160                 } else {
161                         /* Enable Power Down Logic */
162                         gpwrdn.b.pmuintsel = 1;
163                         gpwrdn.b.pmuactv = 1;
164                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
165                                          gpwrdn.d32);
166                 }
167
168                 /* Power off the core */
169                 if (core_if->power_down == 2) {
170                         gpwrdn.d32 = 0;
171                         gpwrdn.b.pwrdnswtch = 1;
172                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
173                                          gpwrdn.d32, 0);
174                 }
175
176                 /* Unmask SRP detected interrupt from Power Down Logic */
177                 gpwrdn.d32 = 0;
178                 gpwrdn.b.srp_det_msk = 1;
179                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
180                                  gpwrdn.d32);
181
182                 dwc_otg_adp_probe_start(core_if);
183                 dwc_otg_dump_global_registers(core_if);
184                 dwc_otg_dump_host_registers(core_if);
185         }
186
187 }
188
189 /**
190  * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
191  * not asserted within 1.1 seconds.
192  *
193  * @param core_if the pointer to core_if strucure.
194  */
195 void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t *core_if)
196 {
197         core_if->adp.vbuson_timer_started = 1;
198         if (core_if->adp.vbuson_timer) {
199                 DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
200                 /* 1.1 secs + 60ms necessary for cil_hcd_start */
201                 DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
202         } else {
203                 DWC_WARN("VBUSON_TIMER = %p\n", core_if->adp.vbuson_timer);
204         }
205 }
206
207 #if 0
208 /**
209  * Masks all DWC OTG core interrupts
210  *
211  */
212 static void mask_all_interrupts(dwc_otg_core_if_t *core_if)
213 {
214         int i;
215         gahbcfg_data_t ahbcfg = {.d32 = 0 };
216
217         /* Mask Host Interrupts */
218
219         /* Clear and disable HCINTs */
220         for (i = 0; i < core_if->core_params->host_channels; i++) {
221                 DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
222                 DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint,
223                                 0xFFFFFFFF);
224
225         }
226
227         /* Clear and disable HAINT */
228         DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
229         DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
230
231         /* Mask Device Interrupts */
232         if (!core_if->multiproc_int_enable) {
233                 /* Clear and disable IN Endpoint interrupts */
234                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
235                 for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
236                         DWC_WRITE_REG32(&core_if->dev_if->
237                                         in_ep_regs[i]->diepint, 0xFFFFFFFF);
238                 }
239
240                 /* Clear and disable OUT Endpoint interrupts */
241                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
242                 for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
243                         DWC_WRITE_REG32(&core_if->dev_if->
244                                         out_ep_regs[i]->doepint, 0xFFFFFFFF);
245                 }
246
247                 /* Clear and disable DAINT */
248                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
249                                 0xFFFFFFFF);
250                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
251         } else {
252                 for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
253                         DWC_WRITE_REG32(&core_if->dev_if->
254                                         dev_global_regs->diepeachintmsk[i], 0);
255                         DWC_WRITE_REG32(&core_if->dev_if->
256                                         in_ep_regs[i]->diepint, 0xFFFFFFFF);
257                 }
258
259                 for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
260                         DWC_WRITE_REG32(&core_if->dev_if->
261                                         dev_global_regs->doepeachintmsk[i], 0);
262                         DWC_WRITE_REG32(&core_if->dev_if->
263                                         out_ep_regs[i]->doepint, 0xFFFFFFFF);
264                 }
265
266                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
267                                 0);
268                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
269                                 0xFFFFFFFF);
270
271         }
272
273         /* Disable interrupts */
274         ahbcfg.b.glblintrmsk = 1;
275         DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
276
277         /* Disable all interrupts. */
278         DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
279
280         /* Clear any pending interrupts */
281         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
282
283         /* Clear any pending OTG Interrupts */
284         DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
285 }
286
287 /**
288  * Unmask Port Connection Detected interrupt
289  *
290  */
291 static void unmask_conn_det_intr(dwc_otg_core_if_t *core_if)
292 {
293         gintmsk_data_t gintmsk = {.d32 = 0, .b.portintr = 1};
294
295         DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
296 }
297 #endif
298
299 /**
300  * Starts the ADP Probing
301  *
302  * @param core_if the pointer to core_if structure.
303  */
304 uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t *core_if)
305 {
306
307         adpctl_data_t adpctl = {.d32 = 0 };
308         gpwrdn_data_t gpwrdn;
309 #if 0
310         adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
311                 .b.adp_sns_int = 1, b.adp_tmout_int
312         };
313 #endif
314         if (core_if->stop_adpprb) {
315                 core_if->stop_adpprb = 0;
316                 return 0;
317         }
318
319         dwc_otg_disable_global_interrupts(core_if);
320         DWC_PRINTF("ADP Probe Start\n");
321         core_if->adp.probe_enabled = 1;
322
323         adpctl.b.adpres = 1;
324         dwc_otg_adp_write_reg(core_if, adpctl.d32);
325
326         while (adpctl.b.adpres)
327                 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
328
329         adpctl.d32 = 0;
330         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
331
332         /* In Host mode unmask SRP detected interrupt */
333         gpwrdn.d32 = 0;
334         gpwrdn.b.sts_chngint_msk = 1;
335
336         if (!gpwrdn.b.idsts)
337                 gpwrdn.b.srp_det_msk = 1;
338
339         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
340
341         adpctl.b.adp_tmout_int_msk = 1;
342         adpctl.b.adp_prb_int_msk = 1;
343         adpctl.b.prb_dschg = 1;
344         adpctl.b.prb_delta = 1;
345         adpctl.b.prb_per = 1;
346         adpctl.b.adpen = 1;
347         adpctl.b.enaprb = 1;
348
349         dwc_otg_adp_write_reg(core_if, adpctl.d32);
350         DWC_PRINTF("ADP Probe Finish\n");
351         return 0;
352 }
353
354 /**
355  * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
356  * within 3 seconds.
357  *
358  * @param core_if the pointer to core_if strucure.
359  */
360 void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t *core_if)
361 {
362         core_if->adp.sense_timer_started = 1;
363         DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3300 /* 3.3 secs */);
364 }
365
366 /**
367  * Starts the ADP Sense
368  *
369  * @param core_if the pointer to core_if strucure.
370  */
371 uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t *core_if)
372 {
373         adpctl_data_t adpctl;
374
375         DWC_PRINTF("ADP Sense Start\n");
376
377         /* Unmask ADP sense interrupt and mask all other from the core */
378         adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
379         adpctl.b.adp_sns_int_msk = 1;
380         dwc_otg_adp_write_reg(core_if, adpctl.d32);
381         dwc_otg_disable_global_interrupts(core_if);     /* vahrama */
382
383         /* Set ADP reset bit */
384         adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
385         adpctl.b.adpres = 1;
386         dwc_otg_adp_write_reg(core_if, adpctl.d32);
387
388         while (adpctl.b.adpres)
389                 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
390
391         adpctl.b.adpres = 0;
392         adpctl.b.adpen = 1;
393         adpctl.b.enasns = 1;
394         dwc_otg_adp_write_reg(core_if, adpctl.d32);
395
396         dwc_otg_adp_sense_timer_start(core_if);
397
398         return 0;
399 }
400
401 /**
402  * Stops the ADP Probing
403  *
404  * @param core_if the pointer to core_if strucure.
405  */
406 uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t *core_if)
407 {
408
409         adpctl_data_t adpctl;
410         DWC_PRINTF("Stop ADP probe\n");
411         core_if->adp.probe_enabled = 0;
412         /* core_if->adp.probe_counter = 0; */
413         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
414
415         adpctl.b.adpen = 0;
416         adpctl.b.adp_prb_int = 1;
417         adpctl.b.adp_tmout_int = 1;
418         adpctl.b.adp_sns_int = 1;
419         dwc_otg_adp_write_reg(core_if, adpctl.d32);
420
421         return 0;
422 }
423
424 /**
425  * Stops the ADP Sensing
426  *
427  * @param core_if the pointer to core_if strucure.
428  */
429 uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t *core_if)
430 {
431         adpctl_data_t adpctl;
432
433         core_if->adp.sense_enabled = 0;
434
435         adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
436         adpctl.b.enasns = 0;
437         adpctl.b.adp_sns_int = 1;
438         dwc_otg_adp_write_reg(core_if, adpctl.d32);
439
440         return 0;
441 }
442
443 /**
444  * Called to turn on the VBUS after initial ADP probe in host mode.
445  * If port power was already enabled in cil_hcd_start function then
446  * only schedule a timer.
447  *
448  * @param core_if the pointer to core_if structure.
449  */
450 void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t *core_if)
451 {
452         hprt0_data_t hprt0 = {.d32 = 0 };
453         hprt0.d32 = dwc_otg_read_hprt0(core_if);
454         DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
455
456         if (hprt0.b.prtpwr == 0) {
457                 hprt0.b.prtpwr = 1;
458                 /* DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); */
459         }
460
461         dwc_otg_adp_vbuson_timer_start(core_if);
462 }
463
464 /**
465  * Called right after driver is loaded
466  * to perform initial actions for ADP
467  *
468  * @param core_if the pointer to core_if structure.
469  * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
470  */
471 void dwc_otg_adp_start(dwc_otg_core_if_t *core_if, uint8_t is_host)
472 {
473         gpwrdn_data_t gpwrdn;
474
475         DWC_PRINTF("ADP Initial Start\n");
476         core_if->adp.adp_started = 1;
477
478         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
479         dwc_otg_disable_global_interrupts(core_if);
480         if (is_host) {
481                 DWC_PRINTF("HOST MODE\n");
482                 /* Enable Power Down Logic Interrupt */
483                 gpwrdn.d32 = 0;
484                 gpwrdn.b.pmuintsel = 1;
485                 gpwrdn.b.pmuactv = 1;
486                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
487                                  gpwrdn.d32);
488                 /* Initialize first ADP probe to obtain Ramp Time value */
489                 core_if->adp.initial_probe = 1;
490                 dwc_otg_adp_probe_start(core_if);
491         } else {
492                 gotgctl_data_t gotgctl;
493                 gotgctl.d32 =
494                     DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
495                 DWC_PRINTF("DEVICE MODE\n");
496                 /* dwc_otg_core_init(core_if); */
497                 if (gotgctl.b.bsesvld == 0) {
498                         /* Enable Power Down Logic Interrupt */
499                         gpwrdn.d32 = 0;
500                         DWC_PRINTF("VBUS is not valid - start ADP probe\n");
501                         gpwrdn.b.pmuintsel = 1;
502                         gpwrdn.b.pmuactv = 1;
503                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
504                                          gpwrdn.d32);
505                         core_if->adp.initial_probe = 1;
506                         dwc_otg_adp_probe_start(core_if);
507                 } else {
508                         DWC_PRINTF
509                             ("VBUS is valid - initialize core as a Device\n");
510                         core_if->op_state = B_PERIPHERAL;
511                         /* dwc_otg_core_init(core_if); */
512                         dwc_otg_enable_global_interrupts(core_if);
513                         cil_pcd_start(core_if);
514                         dwc_otg_dump_global_registers(core_if);
515                         dwc_otg_dump_dev_registers(core_if);
516                 }
517         }
518 }
519
520 void dwc_otg_adp_init(dwc_otg_core_if_t *core_if)
521 {
522         core_if->adp.adp_started = 0;
523         core_if->adp.initial_probe = 0;
524         core_if->adp.probe_timer_values[0] = -1;
525         core_if->adp.probe_timer_values[1] = -1;
526         core_if->adp.probe_enabled = 0;
527         core_if->adp.sense_enabled = 0;
528         core_if->adp.sense_timer_started = 0;
529         core_if->adp.vbuson_timer_started = 0;
530         core_if->adp.probe_counter = 0;
531         core_if->adp.gpwrdn = 0;
532         core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
533         /* Initialize timers */
534         core_if->adp.sense_timer =
535             DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
536         core_if->adp.vbuson_timer =
537             DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
538         if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
539                 DWC_ERROR("Could not allocate memory for ADP timers\n");
540 }
541
542 void dwc_otg_adp_remove(dwc_otg_core_if_t *core_if)
543 {
544         gpwrdn_data_t gpwrdn = {.d32 = 0 };
545         gpwrdn.b.pmuintsel = 1;
546         gpwrdn.b.pmuactv = 1;
547         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
548
549         if (core_if->adp.probe_enabled)
550                 dwc_otg_adp_probe_stop(core_if);
551         if (core_if->adp.sense_enabled)
552                 dwc_otg_adp_sense_stop(core_if);
553         if (core_if->adp.sense_timer_started)
554                 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
555         if (core_if->adp.vbuson_timer_started)
556                 DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
557         DWC_TIMER_FREE(core_if->adp.sense_timer);
558         DWC_TIMER_FREE(core_if->adp.vbuson_timer);
559 }
560
561 /* ADP Interrupt Handlers */
562 /**
563  * This function sets Ramp Timer values
564  */
565 static uint32_t set_timer_value(dwc_otg_core_if_t *core_if, uint32_t val)
566 {
567         if (core_if->adp.probe_timer_values[0] == -1) {
568                 core_if->adp.probe_timer_values[0] = val;
569                 core_if->adp.probe_timer_values[1] = -1;
570                 return 1;
571         } else {
572                 core_if->adp.probe_timer_values[1] =
573                     core_if->adp.probe_timer_values[0];
574                 core_if->adp.probe_timer_values[0] = val;
575                 return 0;
576         }
577 }
578
579 /**
580  * This function compares Ramp Timer values
581  */
582 static uint32_t compare_timer_values(dwc_otg_core_if_t *core_if)
583 {
584         uint32_t diff;
585         DWC_DEBUGPL(DBG_ANY, "timer value 0 %d timer value 1 %d\n",
586                     core_if->adp.probe_timer_values[0],
587                     core_if->adp.probe_timer_values[1]);
588         if (core_if->adp.probe_timer_values[0] >=
589             core_if->adp.probe_timer_values[1])
590                 diff =
591                     core_if->adp.probe_timer_values[0] -
592                     core_if->adp.probe_timer_values[1];
593         else
594                 diff =
595                     core_if->adp.probe_timer_values[1] -
596                     core_if->adp.probe_timer_values[0];
597         if (diff < 3)
598                 return 0;
599         else
600                 return 1;
601 }
602
603 /**
604  * This function handles ADP Probe Interrupts
605  */
606 static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t *core_if,
607                                            uint32_t val)
608 {
609         adpctl_data_t adpctl = {.d32 = 0 };
610         gpwrdn_data_t gpwrdn, temp;
611         adpctl.d32 = val;
612
613         temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
614
615         core_if->adp.gpwrdn =
616             DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
617         if (adpctl.b.rtim == 0 /*&& !temp.b.idsts */) {
618                 DWC_PRINTF("RTIM value is 0\n");
619                 goto exit;
620         }
621         core_if->adp.probe_counter++;
622
623         if (set_timer_value(core_if, adpctl.b.rtim) &&
624             core_if->adp.initial_probe) {
625                 core_if->adp.initial_probe = 0;
626                 dwc_otg_adp_probe_stop(core_if);
627                 gpwrdn.d32 = 0;
628                 gpwrdn.b.pmuactv = 1;
629                 gpwrdn.b.pmuintsel = 1;
630                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
631                                  0);
632                 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,
633                                 0xFFFFFFFF);
634
635                 /* check which value is for device mode and which for Host mode */
636                 if (!temp.b.idsts) {    /* considered host mode value is 0 */
637                         /*
638                          * Turn on VBUS after initial ADP probe.
639                          */
640                         core_if->op_state = A_HOST;
641                         dwc_otg_enable_global_interrupts(core_if);
642                         DWC_SPINUNLOCK(core_if->lock);
643                         cil_hcd_start(core_if);
644                         dwc_otg_adp_turnon_vbus(core_if);
645                         DWC_SPINLOCK(core_if->lock);
646                 } else {
647                         /*
648                          * Initiate SRP after initial ADP probe.
649                          */
650                         dwc_otg_enable_global_interrupts(core_if);
651                         dwc_otg_initiate_srp(core_if);
652                 }
653         } else if (core_if->adp.probe_counter > 2) {
654                 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
655                 if (compare_timer_values(core_if)) {
656                         DWC_PRINTF("Difference in timer values !!! \n");
657                         /* core_if->adp.attached = DWC_OTG_ADP_ATTACHED; */
658                         dwc_otg_adp_probe_stop(core_if);
659
660                         /* Power on the core */
661                         if (core_if->power_down == 2) {
662                                 gpwrdn.b.pwrdnswtch = 1;
663                                 DWC_MODIFY_REG32(&core_if->
664                                                  core_global_regs->gpwrdn, 0,
665                                                  gpwrdn.d32);
666                         }
667
668                         /* check which value is for device mode and which for Host mode */
669                         if (!temp.b.idsts) {    /* considered host mode value is 0 */
670                                 /* Disable Interrupt from Power Down Logic */
671                                 gpwrdn.d32 = 0;
672                                 gpwrdn.b.pmuintsel = 1;
673                                 gpwrdn.b.pmuactv = 1;
674                                 DWC_MODIFY_REG32(&core_if->
675                                                  core_global_regs->gpwrdn,
676                                                  gpwrdn.d32, 0);
677
678                                 /*
679                                  * Initialize the Core for Host mode.
680                                  */
681                                 core_if->op_state = A_HOST;
682                                 dwc_otg_core_init(core_if);
683                                 dwc_otg_enable_global_interrupts(core_if);
684                                 cil_hcd_start(core_if);
685                         } else {
686                                 gotgctl_data_t gotgctl;
687                                 /* Mask SRP detected interrupt from Power Down Logic */
688                                 gpwrdn.d32 = 0;
689                                 gpwrdn.b.srp_det_msk = 1;
690                                 DWC_MODIFY_REG32(&core_if->
691                                                  core_global_regs->gpwrdn,
692                                                  gpwrdn.d32, 0);
693
694                                 /* Disable Power Down Logic */
695                                 gpwrdn.d32 = 0;
696                                 gpwrdn.b.pmuintsel = 1;
697                                 gpwrdn.b.pmuactv = 1;
698                                 DWC_MODIFY_REG32(&core_if->
699                                                  core_global_regs->gpwrdn,
700                                                  gpwrdn.d32, 0);
701
702                                 /*
703                                  * Initialize the Core for Device mode.
704                                  */
705                                 core_if->op_state = B_PERIPHERAL;
706                                 /* dwc_otg_core_init(core_if); */
707                                 cil_pcd_start(core_if);
708                                 dwc_otg_enable_global_interrupts(core_if);
709
710                                 gotgctl.d32 =
711                                     DWC_READ_REG32(&core_if->core_global_regs->
712                                                    gotgctl);
713                                 if (!gotgctl.b.bsesvld)
714                                         dwc_otg_initiate_srp(core_if);
715                         }
716                 }
717                 if (core_if->power_down == 2) {
718                         if (gpwrdn.b.bsessvld) {
719                                 /* Mask SRP detected interrupt from Power Down Logic */
720                                 gpwrdn.d32 = 0;
721                                 gpwrdn.b.srp_det_msk = 1;
722                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
723                                                  gpwrdn, gpwrdn.d32, 0);
724
725                                 /* Disable Power Down Logic */
726                                 gpwrdn.d32 = 0;
727                                 gpwrdn.b.pmuactv = 1;
728                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
729                                                  gpwrdn, gpwrdn.d32, 0);
730
731                                 /*
732                                  * Initialize the Core for Device mode.
733                                  */
734                                 core_if->op_state = B_PERIPHERAL;
735                                 dwc_otg_core_init(core_if);
736                                 dwc_otg_enable_global_interrupts(core_if);
737                                 cil_pcd_start(core_if);
738                         }
739                 }
740         }
741 exit:
742         /* Clear interrupt */
743         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
744         adpctl.b.adp_prb_int = 1;
745         dwc_otg_adp_write_reg(core_if, adpctl.d32);
746
747         return 0;
748 }
749
750 /**
751  * This function hadles ADP Sense Interrupt
752  */
753 static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t *core_if)
754 {
755         adpctl_data_t adpctl;
756         /* Stop ADP Sense timer */
757         DWC_TIMER_CANCEL(core_if->adp.sense_timer);
758
759         /* Restart ADP Sense timer */
760         dwc_otg_adp_sense_timer_start(core_if);
761
762         /* Clear interrupt */
763         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
764         adpctl.b.adp_sns_int = 1;
765         dwc_otg_adp_write_reg(core_if, adpctl.d32);
766
767         return 0;
768 }
769
770 /**
771  * This function handles ADP Probe Interrupts
772  */
773 static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t *core_if,
774                                                  uint32_t val)
775 {
776         adpctl_data_t adpctl = {.d32 = 0 };
777         adpctl.d32 = val;
778         set_timer_value(core_if, adpctl.b.rtim);
779
780         /* Clear interrupt */
781         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
782         adpctl.b.adp_tmout_int = 1;
783         dwc_otg_adp_write_reg(core_if, adpctl.d32);
784
785         return 0;
786 }
787
788 /**
789  * ADP Interrupt handler.
790  *
791  */
792 int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t *core_if)
793 {
794         int retval = 0;
795         adpctl_data_t adpctl = {.d32 = 0 };
796
797         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
798         DWC_PRINTF("ADPCTL = %08x\n", adpctl.d32);
799
800         if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
801                 DWC_PRINTF("ADP Sense interrupt\n");
802                 retval |= dwc_otg_adp_handle_sns_intr(core_if);
803         }
804         if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
805                 DWC_PRINTF("ADP timeout interrupt\n");
806                 retval |=
807                     dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
808         }
809         if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
810                 DWC_PRINTF("ADP Probe interrupt\n");
811                 adpctl.b.adp_prb_int = 1;
812                 retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
813         }
814         /* dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0); */
815         /* dwc_otg_adp_write_reg(core_if, adpctl.d32); */
816         DWC_PRINTF("RETURN FROM ADP ISR\n");
817
818         return retval;
819 }
820
821 /**
822  *
823  * @param core_if Programming view of DWC_otg controller.
824  */
825 int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t *core_if)
826 {
827
828 #ifndef DWC_HOST_ONLY
829         hprt0_data_t hprt0;
830         gpwrdn_data_t gpwrdn;
831         DWC_DEBUGPL(DBG_ANY,
832                     "++ Power Down Logic Session Request Interrupt++\n");
833
834         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
835         /* check which value is for device mode and which for Host mode */
836         if (!gpwrdn.b.idsts) {  /* considered host mode value is 0 */
837                 DWC_PRINTF("SRP: Host mode\n");
838
839                 if (core_if->adp_enable) {
840                         dwc_otg_adp_probe_stop(core_if);
841
842                         /* Power on the core */
843                         if (core_if->power_down == 2) {
844                                 gpwrdn.b.pwrdnswtch = 1;
845                                 DWC_MODIFY_REG32(&core_if->
846                                                  core_global_regs->gpwrdn, 0,
847                                                  gpwrdn.d32);
848                         }
849
850                         core_if->op_state = A_HOST;
851                         dwc_otg_core_init(core_if);
852                         dwc_otg_enable_global_interrupts(core_if);
853                         cil_hcd_start(core_if);
854                 }
855
856                 /* Turn on the port power bit. */
857                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
858                 hprt0.b.prtpwr = 1;
859                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
860
861                 /* Start the Connection timer. So a message can be displayed
862                  * if connect does not occur within 10 seconds. */
863                 cil_hcd_session_start(core_if);
864         } else {
865                 DWC_PRINTF("SRP: Device mode %s\n", __func__);
866                 if (core_if->adp_enable) {
867                         dwc_otg_adp_probe_stop(core_if);
868
869                         /* Power on the core */
870                         if (core_if->power_down == 2) {
871                                 gpwrdn.b.pwrdnswtch = 1;
872                                 DWC_MODIFY_REG32(&core_if->
873                                                  core_global_regs->gpwrdn, 0,
874                                                  gpwrdn.d32);
875                         }
876
877                         gpwrdn.d32 = 0;
878                         gpwrdn.b.pmuactv = 0;
879                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
880                                          gpwrdn.d32);
881
882                         core_if->op_state = B_PERIPHERAL;
883                         dwc_otg_core_init(core_if);
884                         dwc_otg_enable_global_interrupts(core_if);
885                         cil_pcd_start(core_if);
886                 }
887         }
888 #endif
889         return 1;
890 }