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);
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_probe_func(void * ptr)
107 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
108 dwc_otg_adp_probe_start(core_if);
111 static void adp_sense_timeout(void *ptr)
113 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
114 core_if->adp.sense_timer_started = 0;
115 DWC_PRINTF("ADP SENSE TIMEOUT\n");
116 if (core_if->adp_enable) {
117 dwc_otg_adp_sense_stop(core_if);
118 DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, adp_probe_func,
119 core_if, 2500, "start probe");
124 * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
126 static void adp_vbuson_timeout(void *ptr)
128 gpwrdn_data_t gpwrdn;
129 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
130 hprt0_data_t hprt0 = {.d32 = 0 };
131 pcgcctl_data_t pcgcctl = {.d32 = 0 };
132 DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
134 core_if->adp.vbuson_timer_started = 0;
137 DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
140 /* Power off the core */
141 if (core_if->power_down == 2) {
142 /* Enable Wakeup Logic */
143 // gpwrdn.b.wkupactiv = 1;
144 gpwrdn.b.pmuactv = 0;
145 gpwrdn.b.pwrdnrstn = 1;
146 gpwrdn.b.pwrdnclmp = 1;
147 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
150 /* Suspend the Phy Clock */
151 pcgcctl.b.stoppclk = 1;
152 DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
155 // gpwrdn.b.wkupactiv = 1;
156 gpwrdn.b.pmuactv = 1;
157 gpwrdn.b.pwrdnrstn = 1;
158 gpwrdn.b.pwrdnclmp = 1;
159 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
162 /* Enable Power Down Logic */
163 gpwrdn.b.pmuintsel = 1;
164 gpwrdn.b.pmuactv = 1;
165 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
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, gpwrdn.d32);
181 dwc_otg_adp_probe_start(core_if);
182 dwc_otg_dump_global_registers(core_if);
183 dwc_otg_dump_host_registers(core_if);
189 * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
190 * not asserted within 1.1 seconds.
192 * @param core_if the pointer to core_if strucure.
194 void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
196 core_if->adp.vbuson_timer_started = 1;
197 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, 0xFFFFFFFF);
226 /* Clear and disable HAINT */
227 DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
228 DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
230 /* Mask Device Interrupts */
231 if (!core_if->multiproc_int_enable) {
232 /* Clear and disable IN Endpoint interrupts */
233 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
234 for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
235 DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
236 diepint, 0xFFFFFFFF);
239 /* Clear and disable OUT Endpoint interrupts */
240 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
241 for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
242 DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
243 doepint, 0xFFFFFFFF);
246 /* Clear and disable DAINT */
247 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
249 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
251 for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
252 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
253 diepeachintmsk[i], 0);
254 DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
255 diepint, 0xFFFFFFFF);
258 for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
259 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
260 doepeachintmsk[i], 0);
261 DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
262 doepint, 0xFFFFFFFF);
265 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
267 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
272 /* Disable interrupts */
273 ahbcfg.b.glblintrmsk = 1;
274 DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
276 /* Disable all interrupts. */
277 DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
279 /* Clear any pending interrupts */
280 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
282 /* Clear any pending OTG Interrupts */
283 DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
287 * Unmask Port Connection Detected interrupt
290 static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
292 gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
294 DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
299 * Starts the ADP Probing
301 * @param core_if the pointer to core_if structure.
303 uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
306 adpctl_data_t adpctl = {.d32 = 0};
307 gpwrdn_data_t gpwrdn;
309 adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
310 .b.adp_sns_int = 1, b.adp_tmout_int};
312 if (core_if->stop_adpprb) {
313 core_if->stop_adpprb = 0;
317 dwc_otg_disable_global_interrupts(core_if);
318 DWC_PRINTF("ADP Probe Start\n");
319 core_if->adp.probe_enabled = 1;
322 dwc_otg_adp_write_reg(core_if, adpctl.d32);
324 while (adpctl.b.adpres) {
325 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
329 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
331 /* In Host mode unmask SRP detected interrupt */
333 gpwrdn.b.sts_chngint_msk = 1;
334 if (!gpwrdn.b.idsts) {
335 gpwrdn.b.srp_det_msk = 1;
337 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
339 adpctl.b.adp_tmout_int_msk = 1;
340 adpctl.b.adp_prb_int_msk = 1;
341 adpctl.b.prb_dschg = 1;
342 adpctl.b.prb_delta = 1;
343 adpctl.b.prb_per = 1;
347 dwc_otg_adp_write_reg(core_if, adpctl.d32);
348 DWC_PRINTF("ADP Probe Finish\n");
353 * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
356 * @param core_if the pointer to core_if strucure.
358 void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
360 core_if->adp.sense_timer_started = 1;
361 DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3300 /* 3.3 secs */ );
365 * Starts the ADP Sense
367 * @param core_if the pointer to core_if strucure.
369 uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
371 adpctl_data_t adpctl;
373 DWC_PRINTF("ADP Sense Start\n");
375 /* Unmask ADP sense interrupt and mask all other from the core */
376 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
377 adpctl.b.adp_sns_int_msk = 1;
378 dwc_otg_adp_write_reg(core_if, adpctl.d32);
379 dwc_otg_disable_global_interrupts(core_if); // vahrama
381 /* Set ADP reset bit*/
382 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
384 dwc_otg_adp_write_reg(core_if, adpctl.d32);
386 while (adpctl.b.adpres) {
387 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
393 dwc_otg_adp_write_reg(core_if, adpctl.d32);
395 dwc_otg_adp_sense_timer_start(core_if);
401 * Stops the ADP Probing
403 * @param core_if the pointer to core_if strucure.
405 uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
408 adpctl_data_t adpctl;
409 DWC_PRINTF("Stop ADP probe\n");
410 core_if->adp.probe_enabled = 0;
411 //core_if->adp.probe_counter = 0;
412 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
415 adpctl.b.adp_prb_int = 1;
416 adpctl.b.adp_tmout_int = 1;
417 adpctl.b.adp_sns_int = 1;
418 dwc_otg_adp_write_reg(core_if, adpctl.d32);
424 * Stops the ADP Sensing
426 * @param core_if the pointer to core_if strucure.
428 uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
430 adpctl_data_t adpctl;
432 core_if->adp.sense_enabled = 0;
434 adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
436 adpctl.b.adp_sns_int = 1;
437 dwc_otg_adp_write_reg(core_if, adpctl.d32);
443 * Called to turn on the VBUS after initial ADP probe in host mode.
444 * If port power was already enabled in cil_hcd_start function then
445 * only schedule a timer.
447 * @param core_if the pointer to core_if structure.
449 void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
451 hprt0_data_t hprt0 = {.d32 = 0 };
452 hprt0.d32 = dwc_otg_read_hprt0(core_if);
453 DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
455 if (hprt0.b.prtpwr == 0) {
457 //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
460 dwc_otg_adp_vbuson_timer_start(core_if);
464 * Called right after driver is loaded
465 * to perform initial actions for ADP
467 * @param core_if the pointer to core_if structure.
468 * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
470 void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
472 gpwrdn_data_t gpwrdn;
474 DWC_PRINTF("ADP Initial Start\n");
475 core_if->adp.adp_started = 1;
477 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
478 dwc_otg_disable_global_interrupts(core_if);
480 DWC_PRINTF("HOST MODE\n");
481 /* Enable Power Down Logic Interrupt*/
483 gpwrdn.b.pmuintsel = 1;
484 gpwrdn.b.pmuactv = 1;
485 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
486 /* Initialize first ADP probe to obtain Ramp Time value */
487 core_if->adp.initial_probe = 1;
488 dwc_otg_adp_probe_start(core_if);
490 gotgctl_data_t gotgctl;
491 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
492 DWC_PRINTF("DEVICE MODE\n");
493 //dwc_otg_core_init(core_if);
494 if (gotgctl.b.bsesvld == 0) {
495 /* Enable Power Down Logic Interrupt*/
497 DWC_PRINTF("VBUS is not valid - start ADP probe\n");
498 gpwrdn.b.pmuintsel = 1;
499 gpwrdn.b.pmuactv = 1;
500 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
501 core_if->adp.initial_probe = 1;
502 dwc_otg_adp_probe_start(core_if);
504 DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
505 core_if->op_state = B_PERIPHERAL;
506 //dwc_otg_core_init(core_if);
507 dwc_otg_enable_global_interrupts(core_if);
508 cil_pcd_start(core_if);
509 dwc_otg_dump_global_registers(core_if);
510 dwc_otg_dump_dev_registers(core_if);
515 void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
517 core_if->adp.adp_started = 0;
518 core_if->adp.initial_probe = 0;
519 core_if->adp.probe_timer_values[0] = -1;
520 core_if->adp.probe_timer_values[1] = -1;
521 core_if->adp.probe_enabled = 0;
522 core_if->adp.sense_enabled = 0;
523 core_if->adp.sense_timer_started = 0;
524 core_if->adp.vbuson_timer_started = 0;
525 core_if->adp.probe_counter = 0;
526 core_if->adp.gpwrdn = 0;
527 core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
528 /* Initialize timers */
529 core_if->adp.sense_timer =
530 DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
531 core_if->adp.vbuson_timer =
532 DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
533 if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
535 DWC_ERROR("Could not allocate memory for ADP timers\n");
539 void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
541 gpwrdn_data_t gpwrdn = { .d32 = 0 };
542 gpwrdn.b.pmuintsel = 1;
543 gpwrdn.b.pmuactv = 1;
544 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
546 if (core_if->adp.probe_enabled)
547 dwc_otg_adp_probe_stop(core_if);
548 if (core_if->adp.sense_enabled)
549 dwc_otg_adp_sense_stop(core_if);
550 if (core_if->adp.sense_timer_started)
551 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
552 if (core_if->adp.vbuson_timer_started)
553 DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
554 DWC_TIMER_FREE(core_if->adp.sense_timer);
555 DWC_TIMER_FREE(core_if->adp.vbuson_timer);
558 /////////////////////////////////////////////////////////////////////
559 ////////////// ADP Interrupt Handlers ///////////////////////////////
560 /////////////////////////////////////////////////////////////////////
562 * This function sets Ramp Timer values
564 static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
566 if (core_if->adp.probe_timer_values[0] == -1) {
567 core_if->adp.probe_timer_values[0] = val;
568 core_if->adp.probe_timer_values[1] = -1;
571 core_if->adp.probe_timer_values[1] =
572 core_if->adp.probe_timer_values[0];
573 core_if->adp.probe_timer_values[0] = val;
579 * This function compares Ramp Timer values
581 static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
584 DWC_DEBUGPL(DBG_ANY, "timer value 0 %d timer value 1 %d\n",
585 core_if->adp.probe_timer_values[0], core_if->adp.probe_timer_values[1]);
586 if (core_if->adp.probe_timer_values[0] >= core_if->adp.probe_timer_values[1])
587 diff = core_if->adp.probe_timer_values[0] - core_if->adp.probe_timer_values[1];
589 diff = core_if->adp.probe_timer_values[1] - core_if->adp.probe_timer_values[0];
598 * This function handles ADP Probe Interrupts
600 static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
603 adpctl_data_t adpctl = {.d32 = 0 };
604 gpwrdn_data_t gpwrdn, temp;
607 temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
609 core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
610 if (adpctl.b.rtim == 0 /*&& !temp.b.idsts*/){
611 DWC_PRINTF("RTIM value is 0\n");
614 core_if->adp.probe_counter++;
616 if (set_timer_value(core_if, adpctl.b.rtim) &&
617 core_if->adp.initial_probe) {
618 core_if->adp.initial_probe = 0;
619 dwc_otg_adp_probe_stop(core_if);
621 gpwrdn.b.pmuactv = 1;
622 gpwrdn.b.pmuintsel = 1;
623 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
624 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
626 /* check which value is for device mode and which for Host mode */
627 if (!temp.b.idsts) { /* considered host mode value is 0 */
629 * Turn on VBUS after initial ADP probe.
631 core_if->op_state = A_HOST;
632 dwc_otg_enable_global_interrupts(core_if);
633 DWC_SPINUNLOCK(core_if->lock);
634 cil_hcd_start(core_if);
635 dwc_otg_adp_turnon_vbus(core_if);
636 DWC_SPINLOCK(core_if->lock);
639 * Initiate SRP after initial ADP probe.
641 dwc_otg_enable_global_interrupts(core_if);
642 dwc_otg_initiate_srp(core_if);
644 } else if (core_if->adp.probe_counter > 2){
645 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
646 if (compare_timer_values(core_if)) {
647 DWC_PRINTF("Difference in timer values !!! \n");
648 // core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
649 dwc_otg_adp_probe_stop(core_if);
651 /* Power on the core */
652 if (core_if->power_down == 2) {
653 gpwrdn.b.pwrdnswtch = 1;
654 DWC_MODIFY_REG32(&core_if->core_global_regs->
655 gpwrdn, 0, gpwrdn.d32);
658 /* check which value is for device mode and which for Host mode */
659 if (!temp.b.idsts) { /* considered host mode value is 0 */
660 /* Disable Interrupt from Power Down Logic */
662 gpwrdn.b.pmuintsel = 1;
663 gpwrdn.b.pmuactv = 1;
664 DWC_MODIFY_REG32(&core_if->core_global_regs->
665 gpwrdn, gpwrdn.d32, 0);
668 * Initialize the Core for Host mode.
670 core_if->op_state = A_HOST;
671 dwc_otg_core_init(core_if);
672 dwc_otg_enable_global_interrupts(core_if);
673 cil_hcd_start(core_if);
675 gotgctl_data_t gotgctl;
676 /* Mask SRP detected interrupt from Power Down Logic */
678 gpwrdn.b.srp_det_msk = 1;
679 DWC_MODIFY_REG32(&core_if->core_global_regs->
680 gpwrdn, gpwrdn.d32, 0);
682 /* Disable Power Down Logic */
684 gpwrdn.b.pmuintsel = 1;
685 gpwrdn.b.pmuactv = 1;
686 DWC_MODIFY_REG32(&core_if->core_global_regs->
687 gpwrdn, gpwrdn.d32, 0);
690 * Initialize the Core for Device mode.
692 core_if->op_state = B_PERIPHERAL;
693 //dwc_otg_core_init(core_if);
694 cil_pcd_start(core_if);
695 dwc_otg_enable_global_interrupts(core_if);
697 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
698 if (!gotgctl.b.bsesvld)
699 dwc_otg_initiate_srp(core_if);
702 if (core_if->power_down == 2) {
703 if (gpwrdn.b.bsessvld) {
704 /* Mask SRP detected interrupt from Power Down Logic */
706 gpwrdn.b.srp_det_msk = 1;
707 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
709 /* Disable Power Down Logic */
711 gpwrdn.b.pmuactv = 1;
712 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
715 * Initialize the Core for Device mode.
717 core_if->op_state = B_PERIPHERAL;
718 dwc_otg_core_init(core_if);
719 dwc_otg_enable_global_interrupts(core_if);
720 cil_pcd_start(core_if);
725 /* Clear interrupt */
726 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
727 adpctl.b.adp_prb_int = 1;
728 dwc_otg_adp_write_reg(core_if, adpctl.d32);
734 * This function hadles ADP Sense Interrupt
736 static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
738 adpctl_data_t adpctl;
739 /* Stop ADP Sense timer */
740 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
742 /* Restart ADP Sense timer */
743 dwc_otg_adp_sense_timer_start(core_if);
745 /* Clear interrupt */
746 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
747 adpctl.b.adp_sns_int = 1;
748 dwc_otg_adp_write_reg(core_if, adpctl.d32);
754 * This function handles ADP Probe Interrupts
756 static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
759 adpctl_data_t adpctl = {.d32 = 0 };
761 set_timer_value(core_if, adpctl.b.rtim);
763 /* Clear interrupt */
764 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
765 adpctl.b.adp_tmout_int = 1;
766 dwc_otg_adp_write_reg(core_if, adpctl.d32);
772 * ADP Interrupt handler.
775 int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
778 adpctl_data_t adpctl = {.d32 = 0};
780 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
781 DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
783 if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
784 DWC_PRINTF("ADP Sense interrupt\n");
785 retval |= dwc_otg_adp_handle_sns_intr(core_if);
787 if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
788 DWC_PRINTF("ADP timeout interrupt\n");
789 retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
791 if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
792 DWC_PRINTF("ADP Probe interrupt\n");
793 adpctl.b.adp_prb_int = 1;
794 retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
797 // dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
798 //dwc_otg_adp_write_reg(core_if, adpctl.d32);
799 DWC_PRINTF("RETURN FROM ADP ISR\n");
806 * @param core_if Programming view of DWC_otg controller.
808 int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
811 #ifndef DWC_HOST_ONLY
813 gpwrdn_data_t gpwrdn;
814 DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
816 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
817 /* check which value is for device mode and which for Host mode */
818 if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */
819 DWC_PRINTF("SRP: Host mode\n");
821 if (core_if->adp_enable) {
822 dwc_otg_adp_probe_stop(core_if);
824 /* Power on the core */
825 if (core_if->power_down == 2) {
826 gpwrdn.b.pwrdnswtch = 1;
827 DWC_MODIFY_REG32(&core_if->core_global_regs->
828 gpwrdn, 0, gpwrdn.d32);
831 core_if->op_state = A_HOST;
832 dwc_otg_core_init(core_if);
833 dwc_otg_enable_global_interrupts(core_if);
834 cil_hcd_start(core_if);
837 /* Turn on the port power bit. */
838 hprt0.d32 = dwc_otg_read_hprt0(core_if);
840 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
842 /* Start the Connection timer. So a message can be displayed
843 * if connect does not occur within 10 seconds. */
844 cil_hcd_session_start(core_if);
846 DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
847 if (core_if->adp_enable) {
848 dwc_otg_adp_probe_stop(core_if);
850 /* Power on the core */
851 if (core_if->power_down == 2) {
852 gpwrdn.b.pwrdnswtch = 1;
853 DWC_MODIFY_REG32(&core_if->core_global_regs->
854 gpwrdn, 0, gpwrdn.d32);
858 gpwrdn.b.pmuactv = 0;
859 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
862 core_if->op_state = B_PERIPHERAL;
863 dwc_otg_core_init(core_if);
864 dwc_otg_enable_global_interrupts(core_if);
865 cil_pcd_start(core_if);