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 * ========================================================================== */
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"
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);
61 * Function is called to read ADP registers
63 uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t *core_if)
70 DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
73 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
79 * Function is called to read ADPCTL register and filter Write-clear bits
81 uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t *core_if)
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;
94 * Function is called to write ADP registers
96 void dwc_otg_adp_modify_reg(dwc_otg_core_if_t *core_if, uint32_t clr,
99 dwc_otg_adp_write_reg(core_if,
100 (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
103 static void adp_probe_func(void *ptr)
105 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
106 dwc_otg_adp_probe_start(core_if);
109 static void adp_sense_timeout(void *ptr)
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");
122 * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
124 static void adp_vbuson_timeout(void *ptr)
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",
133 core_if->adp.vbuson_timer_started = 0;
136 DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
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,
149 /* Suspend the Phy Clock */
150 pcgcctl.b.stoppclk = 1;
151 DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
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,
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,
168 /* Power off the core */
169 if (core_if->power_down == 2) {
171 gpwrdn.b.pwrdnswtch = 1;
172 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
176 /* Unmask SRP detected interrupt from Power Down Logic */
178 gpwrdn.b.srp_det_msk = 1;
179 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
182 dwc_otg_adp_probe_start(core_if);
183 dwc_otg_dump_global_registers(core_if);
184 dwc_otg_dump_host_registers(core_if);
190 * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
191 * not asserted within 1.1 seconds.
193 * @param core_if the pointer to core_if strucure.
195 void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t *core_if)
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);
203 DWC_WARN("VBUSON_TIMER = %p\n", core_if->adp.vbuson_timer);
209 * Masks all DWC OTG core interrupts
212 static void mask_all_interrupts(dwc_otg_core_if_t *core_if)
215 gahbcfg_data_t ahbcfg = {.d32 = 0 };
217 /* Mask Host Interrupts */
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,
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);
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);
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);
247 /* Clear and disable DAINT */
248 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
250 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
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);
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);
266 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
268 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
273 /* Disable interrupts */
274 ahbcfg.b.glblintrmsk = 1;
275 DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
277 /* Disable all interrupts. */
278 DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
280 /* Clear any pending interrupts */
281 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
283 /* Clear any pending OTG Interrupts */
284 DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
288 * Unmask Port Connection Detected interrupt
291 static void unmask_conn_det_intr(dwc_otg_core_if_t *core_if)
293 gintmsk_data_t gintmsk = {.d32 = 0, .b.portintr = 1};
295 DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
300 * Starts the ADP Probing
302 * @param core_if the pointer to core_if structure.
304 uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t *core_if)
307 adpctl_data_t adpctl = {.d32 = 0 };
308 gpwrdn_data_t gpwrdn;
310 adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
311 .b.adp_sns_int = 1, b.adp_tmout_int
314 if (core_if->stop_adpprb) {
315 core_if->stop_adpprb = 0;
319 dwc_otg_disable_global_interrupts(core_if);
320 DWC_PRINTF("ADP Probe Start\n");
321 core_if->adp.probe_enabled = 1;
324 dwc_otg_adp_write_reg(core_if, adpctl.d32);
326 while (adpctl.b.adpres)
327 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
330 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
332 /* In Host mode unmask SRP detected interrupt */
334 gpwrdn.b.sts_chngint_msk = 1;
337 gpwrdn.b.srp_det_msk = 1;
339 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
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;
349 dwc_otg_adp_write_reg(core_if, adpctl.d32);
350 DWC_PRINTF("ADP Probe Finish\n");
355 * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
358 * @param core_if the pointer to core_if strucure.
360 void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t *core_if)
362 core_if->adp.sense_timer_started = 1;
363 DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3300 /* 3.3 secs */);
367 * Starts the ADP Sense
369 * @param core_if the pointer to core_if strucure.
371 uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t *core_if)
373 adpctl_data_t adpctl;
375 DWC_PRINTF("ADP Sense Start\n");
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 */
383 /* Set ADP reset bit */
384 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
386 dwc_otg_adp_write_reg(core_if, adpctl.d32);
388 while (adpctl.b.adpres)
389 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
394 dwc_otg_adp_write_reg(core_if, adpctl.d32);
396 dwc_otg_adp_sense_timer_start(core_if);
402 * Stops the ADP Probing
404 * @param core_if the pointer to core_if strucure.
406 uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t *core_if)
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);
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);
425 * Stops the ADP Sensing
427 * @param core_if the pointer to core_if strucure.
429 uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t *core_if)
431 adpctl_data_t adpctl;
433 core_if->adp.sense_enabled = 0;
435 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
437 adpctl.b.adp_sns_int = 1;
438 dwc_otg_adp_write_reg(core_if, adpctl.d32);
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.
448 * @param core_if the pointer to core_if structure.
450 void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t *core_if)
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);
456 if (hprt0.b.prtpwr == 0) {
458 /* DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); */
461 dwc_otg_adp_vbuson_timer_start(core_if);
465 * Called right after driver is loaded
466 * to perform initial actions for ADP
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
471 void dwc_otg_adp_start(dwc_otg_core_if_t *core_if, uint8_t is_host)
473 gpwrdn_data_t gpwrdn;
475 DWC_PRINTF("ADP Initial Start\n");
476 core_if->adp.adp_started = 1;
478 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
479 dwc_otg_disable_global_interrupts(core_if);
481 DWC_PRINTF("HOST MODE\n");
482 /* Enable Power Down Logic Interrupt */
484 gpwrdn.b.pmuintsel = 1;
485 gpwrdn.b.pmuactv = 1;
486 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
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);
492 gotgctl_data_t gotgctl;
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 */
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,
505 core_if->adp.initial_probe = 1;
506 dwc_otg_adp_probe_start(core_if);
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);
520 void dwc_otg_adp_init(dwc_otg_core_if_t *core_if)
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");
542 void dwc_otg_adp_remove(dwc_otg_core_if_t *core_if)
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);
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);
561 /* ADP Interrupt Handlers */
563 * This function sets Ramp Timer values
565 static uint32_t set_timer_value(dwc_otg_core_if_t *core_if, uint32_t val)
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;
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;
580 * This function compares Ramp Timer values
582 static uint32_t compare_timer_values(dwc_otg_core_if_t *core_if)
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])
591 core_if->adp.probe_timer_values[0] -
592 core_if->adp.probe_timer_values[1];
595 core_if->adp.probe_timer_values[1] -
596 core_if->adp.probe_timer_values[0];
604 * This function handles ADP Probe Interrupts
606 static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t *core_if,
609 adpctl_data_t adpctl = {.d32 = 0 };
610 gpwrdn_data_t gpwrdn, temp;
613 temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
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");
621 core_if->adp.probe_counter++;
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);
628 gpwrdn.b.pmuactv = 1;
629 gpwrdn.b.pmuintsel = 1;
630 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32,
632 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,
635 /* check which value is for device mode and which for Host mode */
636 if (!temp.b.idsts) { /* considered host mode value is 0 */
638 * Turn on VBUS after initial ADP probe.
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);
648 * Initiate SRP after initial ADP probe.
650 dwc_otg_enable_global_interrupts(core_if);
651 dwc_otg_initiate_srp(core_if);
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);
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,
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 */
672 gpwrdn.b.pmuintsel = 1;
673 gpwrdn.b.pmuactv = 1;
674 DWC_MODIFY_REG32(&core_if->
675 core_global_regs->gpwrdn,
679 * Initialize the Core for Host mode.
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);
686 gotgctl_data_t gotgctl;
687 /* Mask SRP detected interrupt from Power Down Logic */
689 gpwrdn.b.srp_det_msk = 1;
690 DWC_MODIFY_REG32(&core_if->
691 core_global_regs->gpwrdn,
694 /* Disable Power Down Logic */
696 gpwrdn.b.pmuintsel = 1;
697 gpwrdn.b.pmuactv = 1;
698 DWC_MODIFY_REG32(&core_if->
699 core_global_regs->gpwrdn,
703 * Initialize the Core for Device mode.
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);
711 DWC_READ_REG32(&core_if->core_global_regs->
713 if (!gotgctl.b.bsesvld)
714 dwc_otg_initiate_srp(core_if);
717 if (core_if->power_down == 2) {
718 if (gpwrdn.b.bsessvld) {
719 /* Mask SRP detected interrupt from Power Down Logic */
721 gpwrdn.b.srp_det_msk = 1;
722 DWC_MODIFY_REG32(&core_if->core_global_regs->
723 gpwrdn, gpwrdn.d32, 0);
725 /* Disable Power Down Logic */
727 gpwrdn.b.pmuactv = 1;
728 DWC_MODIFY_REG32(&core_if->core_global_regs->
729 gpwrdn, gpwrdn.d32, 0);
732 * Initialize the Core for Device mode.
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);
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);
751 * This function hadles ADP Sense Interrupt
753 static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t *core_if)
755 adpctl_data_t adpctl;
756 /* Stop ADP Sense timer */
757 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
759 /* Restart ADP Sense timer */
760 dwc_otg_adp_sense_timer_start(core_if);
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);
771 * This function handles ADP Probe Interrupts
773 static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t *core_if,
776 adpctl_data_t adpctl = {.d32 = 0 };
778 set_timer_value(core_if, adpctl.b.rtim);
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);
789 * ADP Interrupt handler.
792 int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t *core_if)
795 adpctl_data_t adpctl = {.d32 = 0 };
797 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
798 DWC_PRINTF("ADPCTL = %08x\n", adpctl.d32);
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);
804 if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
805 DWC_PRINTF("ADP timeout interrupt\n");
807 dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
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);
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");
823 * @param core_if Programming view of DWC_otg controller.
825 int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t *core_if)
828 #ifndef DWC_HOST_ONLY
830 gpwrdn_data_t gpwrdn;
832 "++ Power Down Logic Session Request Interrupt++\n");
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");
839 if (core_if->adp_enable) {
840 dwc_otg_adp_probe_stop(core_if);
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,
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);
856 /* Turn on the port power bit. */
857 hprt0.d32 = dwc_otg_read_hprt0(core_if);
859 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
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);
865 DWC_PRINTF("SRP: Device mode %s\n", __func__);
866 if (core_if->adp_enable) {
867 dwc_otg_adp_probe_stop(core_if);
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,
878 gpwrdn.b.pmuactv = 0;
879 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
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);