1 /* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
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.
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.
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
32 * ========================================================================== */
35 #include "dwc_otg_regs.h"
36 #include "dwc_otg_cil.h"
37 #include "dwc_otg_adp.h"
41 * This file contains the most of the Attach Detect Protocol implementation for
42 * the driver to support OTG Rev2.0.
46 void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
53 DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
56 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
62 * Function is called to read ADP registers
64 uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
71 DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
74 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
81 * Function is called to read ADPCTL register and filter Write-clear bits
83 uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
87 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
88 adpctl.b.adp_tmout_int = 0;
89 adpctl.b.adp_prb_int = 0;
90 adpctl.b.adp_tmout_int = 0;
96 * Function is called to write ADP registers
98 void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
101 dwc_otg_adp_write_reg(core_if,
102 (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
105 static void adp_sense_timeout(void *ptr)
107 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
108 core_if->adp.sense_timer_started = 0;
109 DWC_PRINTF("ADP SENSE TIMEOUT\n");
110 if (core_if->adp_enable) {
111 dwc_otg_adp_sense_stop(core_if);
112 dwc_otg_adp_probe_start(core_if);
117 * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
119 static void adp_vbuson_timeout(void *ptr)
121 gpwrdn_data_t gpwrdn;
122 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
123 hprt0_data_t hprt0 = {.d32 = 0 };
124 pcgcctl_data_t pcgcctl = {.d32 = 0 };
125 DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
127 core_if->adp.vbuson_timer_started = 0;
130 DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
133 /* Power off the core */
134 if (core_if->power_down == 2) {
135 /* Enable Wakeup Logic */
136 // gpwrdn.b.wkupactiv = 1;
137 gpwrdn.b.pmuactv = 0;
138 gpwrdn.b.pwrdnrstn = 1;
139 gpwrdn.b.pwrdnclmp = 1;
140 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
143 /* Suspend the Phy Clock */
144 pcgcctl.b.stoppclk = 1;
145 DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
148 // gpwrdn.b.wkupactiv = 1;
149 gpwrdn.b.pmuactv = 1;
150 gpwrdn.b.pwrdnrstn = 1;
151 gpwrdn.b.pwrdnclmp = 1;
152 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
155 /* Enable Power Down Logic */
156 gpwrdn.b.pmuintsel = 1;
157 gpwrdn.b.pmuactv = 1;
158 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
161 /* Power off the core */
162 if (core_if->power_down == 2) {
164 gpwrdn.b.pwrdnswtch = 1;
165 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
169 /* Unmask SRP detected interrupt from Power Down Logic */
171 gpwrdn.b.srp_det_msk = 1;
172 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
174 dwc_otg_adp_probe_start(core_if);
175 dwc_otg_dump_global_registers(core_if);
176 dwc_otg_dump_host_registers(core_if);
182 * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
183 * not asserted within 1.1 seconds.
185 * @param core_if the pointer to core_if strucure.
187 void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
189 core_if->adp.vbuson_timer_started = 1;
190 if (core_if->adp.vbuson_timer)
192 DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
193 /* 1.1 secs + 60ms necessary for cil_hcd_start*/
194 DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
196 DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
202 * Masks all DWC OTG core interrupts
205 static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
208 gahbcfg_data_t ahbcfg = {.d32 = 0 };
210 /* Mask Host Interrupts */
212 /* Clear and disable HCINTs */
213 for (i = 0; i < core_if->core_params->host_channels; i++) {
214 DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
215 DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
219 /* Clear and disable HAINT */
220 DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
221 DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
223 /* Mask Device Interrupts */
224 if (!core_if->multiproc_int_enable) {
225 /* Clear and disable IN Endpoint interrupts */
226 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
227 for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
228 DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
229 diepint, 0xFFFFFFFF);
232 /* Clear and disable OUT Endpoint interrupts */
233 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
234 for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
235 DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
236 doepint, 0xFFFFFFFF);
239 /* Clear and disable DAINT */
240 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
242 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
244 for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
245 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
246 diepeachintmsk[i], 0);
247 DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
248 diepint, 0xFFFFFFFF);
251 for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
252 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
253 doepeachintmsk[i], 0);
254 DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
255 doepint, 0xFFFFFFFF);
258 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
260 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
265 /* Disable interrupts */
266 ahbcfg.b.glblintrmsk = 1;
267 DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
269 /* Disable all interrupts. */
270 DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
272 /* Clear any pending interrupts */
273 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
275 /* Clear any pending OTG Interrupts */
276 DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
280 * Unmask Port Connection Detected interrupt
283 static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
285 gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
287 DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
292 * Starts the ADP Probing
294 * @param core_if the pointer to core_if structure.
296 uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
299 adpctl_data_t adpctl = {.d32 = 0};
300 gpwrdn_data_t gpwrdn;
302 adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
303 .b.adp_sns_int = 1, b.adp_tmout_int};
305 dwc_otg_disable_global_interrupts(core_if);
306 DWC_PRINTF("ADP Probe Start\n");
307 core_if->adp.probe_enabled = 1;
310 dwc_otg_adp_write_reg(core_if, adpctl.d32);
312 while (adpctl.b.adpres) {
313 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
317 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
319 /* In Host mode unmask SRP detected interrupt */
321 gpwrdn.b.sts_chngint_msk = 1;
322 if (!gpwrdn.b.idsts) {
323 gpwrdn.b.srp_det_msk = 1;
325 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
327 adpctl.b.adp_tmout_int_msk = 1;
328 adpctl.b.adp_prb_int_msk = 1;
329 adpctl.b.prb_dschg = 1;
330 adpctl.b.prb_delta = 1;
331 adpctl.b.prb_per = 1;
335 dwc_otg_adp_write_reg(core_if, adpctl.d32);
336 DWC_PRINTF("ADP Probe Finish\n");
341 * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
344 * @param core_if the pointer to core_if strucure.
346 void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
348 core_if->adp.sense_timer_started = 1;
349 DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
353 * Starts the ADP Sense
355 * @param core_if the pointer to core_if strucure.
357 uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
359 adpctl_data_t adpctl;
361 DWC_PRINTF("ADP Sense Start\n");
363 /* Unmask ADP sense interrupt and mask all other from the core */
364 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
365 adpctl.b.adp_sns_int_msk = 1;
366 dwc_otg_adp_write_reg(core_if, adpctl.d32);
367 dwc_otg_disable_global_interrupts(core_if); // vahrama
369 /* Set ADP reset bit*/
370 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
372 dwc_otg_adp_write_reg(core_if, adpctl.d32);
374 while (adpctl.b.adpres) {
375 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
381 dwc_otg_adp_write_reg(core_if, adpctl.d32);
383 dwc_otg_adp_sense_timer_start(core_if);
389 * Stops the ADP Probing
391 * @param core_if the pointer to core_if strucure.
393 uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
396 adpctl_data_t adpctl;
397 DWC_PRINTF("Stop ADP probe\n");
398 core_if->adp.probe_enabled = 0;
399 core_if->adp.probe_counter = 0;
400 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
403 adpctl.b.adp_prb_int = 1;
404 adpctl.b.adp_tmout_int = 1;
405 adpctl.b.adp_sns_int = 1;
406 dwc_otg_adp_write_reg(core_if, adpctl.d32);
412 * Stops the ADP Sensing
414 * @param core_if the pointer to core_if strucure.
416 uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
418 adpctl_data_t adpctl;
420 core_if->adp.sense_enabled = 0;
422 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
424 adpctl.b.adp_sns_int = 1;
425 dwc_otg_adp_write_reg(core_if, adpctl.d32);
431 * Called to turn on the VBUS after initial ADP probe in host mode.
432 * If port power was already enabled in cil_hcd_start function then
433 * only schedule a timer.
435 * @param core_if the pointer to core_if structure.
437 void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
439 hprt0_data_t hprt0 = {.d32 = 0 };
440 hprt0.d32 = dwc_otg_read_hprt0(core_if);
441 DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
443 if (hprt0.b.prtpwr == 0) {
445 //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
448 dwc_otg_adp_vbuson_timer_start(core_if);
452 * Called right after driver is loaded
453 * to perform initial actions for ADP
455 * @param core_if the pointer to core_if structure.
456 * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
458 void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
460 gpwrdn_data_t gpwrdn;
462 DWC_PRINTF("ADP Initial Start\n");
463 core_if->adp.adp_started = 1;
465 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
466 dwc_otg_disable_global_interrupts(core_if);
468 DWC_PRINTF("HOST MODE\n");
469 /* Enable Power Down Logic Interrupt*/
471 gpwrdn.b.pmuintsel = 1;
472 gpwrdn.b.pmuactv = 1;
473 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
474 /* Initialize first ADP probe to obtain Ramp Time value */
475 core_if->adp.initial_probe = 1;
476 dwc_otg_adp_probe_start(core_if);
478 gotgctl_data_t gotgctl;
479 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
480 DWC_PRINTF("DEVICE MODE\n");
481 if (gotgctl.b.bsesvld == 0) {
482 /* Enable Power Down Logic Interrupt*/
484 DWC_PRINTF("VBUS is not valid - start ADP probe\n");
485 gpwrdn.b.pmuintsel = 1;
486 gpwrdn.b.pmuactv = 1;
487 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
488 core_if->adp.initial_probe = 1;
489 dwc_otg_adp_probe_start(core_if);
491 DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
492 core_if->op_state = B_PERIPHERAL;
493 dwc_otg_core_init(core_if);
494 dwc_otg_enable_global_interrupts(core_if);
495 cil_pcd_start(core_if);
496 dwc_otg_dump_global_registers(core_if);
497 dwc_otg_dump_dev_registers(core_if);
502 void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
504 core_if->adp.adp_started = 0;
505 core_if->adp.initial_probe = 0;
506 core_if->adp.probe_timer_values[0] = -1;
507 core_if->adp.probe_timer_values[1] = -1;
508 core_if->adp.probe_enabled = 0;
509 core_if->adp.sense_enabled = 0;
510 core_if->adp.sense_timer_started = 0;
511 core_if->adp.vbuson_timer_started = 0;
512 core_if->adp.probe_counter = 0;
513 core_if->adp.gpwrdn = 0;
514 core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
515 /* Initialize timers */
516 core_if->adp.sense_timer =
517 DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
518 core_if->adp.vbuson_timer =
519 DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
520 if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
522 DWC_ERROR("Could not allocate memory for ADP timers\n");
526 void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
528 gpwrdn_data_t gpwrdn = { .d32 = 0 };
529 gpwrdn.b.pmuintsel = 1;
530 gpwrdn.b.pmuactv = 1;
531 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
533 if (core_if->adp.probe_enabled)
534 dwc_otg_adp_probe_stop(core_if);
535 if (core_if->adp.sense_enabled)
536 dwc_otg_adp_sense_stop(core_if);
537 if (core_if->adp.sense_timer_started)
538 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
539 if (core_if->adp.vbuson_timer_started)
540 DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
541 DWC_TIMER_FREE(core_if->adp.sense_timer);
542 DWC_TIMER_FREE(core_if->adp.vbuson_timer);
545 /////////////////////////////////////////////////////////////////////
546 ////////////// ADP Interrupt Handlers ///////////////////////////////
547 /////////////////////////////////////////////////////////////////////
549 * This function sets Ramp Timer values
551 static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
553 if (core_if->adp.probe_timer_values[0] == -1) {
554 core_if->adp.probe_timer_values[0] = val;
555 core_if->adp.probe_timer_values[1] = -1;
558 core_if->adp.probe_timer_values[1] =
559 core_if->adp.probe_timer_values[0];
560 core_if->adp.probe_timer_values[0] = val;
566 * This function compares Ramp Timer values
568 static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
571 if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
572 diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
574 diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];
583 * This function handles ADP Probe Interrupts
585 static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
588 adpctl_data_t adpctl = {.d32 = 0 };
589 gpwrdn_data_t gpwrdn, temp;
592 temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
593 core_if->adp.probe_counter++;
594 core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
595 if (adpctl.b.rtim == 0 && !temp.b.idsts){
596 DWC_PRINTF("RTIM value is 0\n");
599 if (set_timer_value(core_if, adpctl.b.rtim) &&
600 core_if->adp.initial_probe) {
601 core_if->adp.initial_probe = 0;
602 dwc_otg_adp_probe_stop(core_if);
604 gpwrdn.b.pmuactv = 1;
605 gpwrdn.b.pmuintsel = 1;
606 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
607 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
609 /* check which value is for device mode and which for Host mode */
610 if (!temp.b.idsts) { /* considered host mode value is 0 */
612 * Turn on VBUS after initial ADP probe.
614 core_if->op_state = A_HOST;
615 dwc_otg_enable_global_interrupts(core_if);
616 DWC_SPINUNLOCK(core_if->lock);
617 cil_hcd_start(core_if);
618 dwc_otg_adp_turnon_vbus(core_if);
619 DWC_SPINLOCK(core_if->lock);
622 * Initiate SRP after initial ADP probe.
624 dwc_otg_enable_global_interrupts(core_if);
625 dwc_otg_initiate_srp(core_if);
627 } else if (core_if->adp.probe_counter > 2){
628 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
629 if (compare_timer_values(core_if)) {
630 DWC_PRINTF("Difference in timer values !!! \n");
631 // core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
632 dwc_otg_adp_probe_stop(core_if);
634 /* Power on the core */
635 if (core_if->power_down == 2) {
636 gpwrdn.b.pwrdnswtch = 1;
637 DWC_MODIFY_REG32(&core_if->core_global_regs->
638 gpwrdn, 0, gpwrdn.d32);
641 /* check which value is for device mode and which for Host mode */
642 if (!temp.b.idsts) { /* considered host mode value is 0 */
643 /* Disable Interrupt from Power Down Logic */
645 gpwrdn.b.pmuintsel = 1;
646 gpwrdn.b.pmuactv = 1;
647 DWC_MODIFY_REG32(&core_if->core_global_regs->
648 gpwrdn, gpwrdn.d32, 0);
651 * Initialize the Core for Host mode.
653 core_if->op_state = A_HOST;
654 dwc_otg_core_init(core_if);
655 dwc_otg_enable_global_interrupts(core_if);
656 cil_hcd_start(core_if);
658 gotgctl_data_t gotgctl;
659 /* Mask SRP detected interrupt from Power Down Logic */
661 gpwrdn.b.srp_det_msk = 1;
662 DWC_MODIFY_REG32(&core_if->core_global_regs->
663 gpwrdn, gpwrdn.d32, 0);
665 /* Disable Power Down Logic */
667 gpwrdn.b.pmuintsel = 1;
668 gpwrdn.b.pmuactv = 1;
669 DWC_MODIFY_REG32(&core_if->core_global_regs->
670 gpwrdn, gpwrdn.d32, 0);
673 * Initialize the Core for Device mode.
675 core_if->op_state = B_PERIPHERAL;
676 dwc_otg_core_init(core_if);
677 dwc_otg_enable_global_interrupts(core_if);
678 cil_pcd_start(core_if);
680 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
681 if (!gotgctl.b.bsesvld) {
682 dwc_otg_initiate_srp(core_if);
686 if (core_if->power_down == 2) {
687 if (gpwrdn.b.bsessvld) {
688 /* Mask SRP detected interrupt from Power Down Logic */
690 gpwrdn.b.srp_det_msk = 1;
691 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
693 /* Disable Power Down Logic */
695 gpwrdn.b.pmuactv = 1;
696 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
699 * Initialize the Core for Device mode.
701 core_if->op_state = B_PERIPHERAL;
702 dwc_otg_core_init(core_if);
703 dwc_otg_enable_global_interrupts(core_if);
704 cil_pcd_start(core_if);
709 /* Clear interrupt */
710 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
711 adpctl.b.adp_prb_int = 1;
712 dwc_otg_adp_write_reg(core_if, adpctl.d32);
718 * This function hadles ADP Sense Interrupt
720 static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
722 adpctl_data_t adpctl;
723 /* Stop ADP Sense timer */
724 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
726 /* Restart ADP Sense timer */
727 dwc_otg_adp_sense_timer_start(core_if);
729 /* Clear interrupt */
730 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
731 adpctl.b.adp_sns_int = 1;
732 dwc_otg_adp_write_reg(core_if, adpctl.d32);
738 * This function handles ADP Probe Interrupts
740 static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
743 adpctl_data_t adpctl = {.d32 = 0 };
745 set_timer_value(core_if, adpctl.b.rtim);
747 /* Clear interrupt */
748 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
749 adpctl.b.adp_tmout_int = 1;
750 dwc_otg_adp_write_reg(core_if, adpctl.d32);
756 * ADP Interrupt handler.
759 int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
762 adpctl_data_t adpctl = {.d32 = 0};
764 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
765 DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
767 if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
768 DWC_PRINTF("ADP Sense interrupt\n");
769 retval |= dwc_otg_adp_handle_sns_intr(core_if);
771 if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
772 DWC_PRINTF("ADP timeout interrupt\n");
773 retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
775 if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
776 DWC_PRINTF("ADP Probe interrupt\n");
777 adpctl.b.adp_prb_int = 1;
778 retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
781 // dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
782 //dwc_otg_adp_write_reg(core_if, adpctl.d32);
783 DWC_PRINTF("RETURN FROM ADP ISR\n");
790 * @param core_if Programming view of DWC_otg controller.
792 int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
795 #ifndef DWC_HOST_ONLY
797 gpwrdn_data_t gpwrdn;
798 DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
800 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
801 /* check which value is for device mode and which for Host mode */
802 if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */
803 DWC_PRINTF("SRP: Host mode\n");
805 if (core_if->adp_enable) {
806 dwc_otg_adp_probe_stop(core_if);
808 /* Power on the core */
809 if (core_if->power_down == 2) {
810 gpwrdn.b.pwrdnswtch = 1;
811 DWC_MODIFY_REG32(&core_if->core_global_regs->
812 gpwrdn, 0, gpwrdn.d32);
815 core_if->op_state = A_HOST;
816 dwc_otg_core_init(core_if);
817 dwc_otg_enable_global_interrupts(core_if);
818 cil_hcd_start(core_if);
821 /* Turn on the port power bit. */
822 hprt0.d32 = dwc_otg_read_hprt0(core_if);
824 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
826 /* Start the Connection timer. So a message can be displayed
827 * if connect does not occur within 10 seconds. */
828 cil_hcd_session_start(core_if);
830 DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
831 if (core_if->adp_enable) {
832 dwc_otg_adp_probe_stop(core_if);
834 /* Power on the core */
835 if (core_if->power_down == 2) {
836 gpwrdn.b.pwrdnswtch = 1;
837 DWC_MODIFY_REG32(&core_if->core_global_regs->
838 gpwrdn, 0, gpwrdn.d32);
842 gpwrdn.b.pmuactv = 0;
843 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
846 core_if->op_state = B_PERIPHERAL;
847 dwc_otg_core_init(core_if);
848 dwc_otg_enable_global_interrupts(core_if);
849 cil_pcd_start(core_if);