Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

dwc_otg_adp.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
00003  * $Revision: #12 $
00004  * $Date: 2011/10/26 $
00005  * $Change: 1873028 $
00006  *
00007  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
00008  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
00009  * otherwise expressly agreed to in writing between Synopsys and you.
00010  *
00011  * The Software IS NOT an item of Licensed Software or Licensed Product under
00012  * any End User Software License Agreement or Agreement for Licensed Product
00013  * with Synopsys or any supplement thereto. You are permitted to use and
00014  * redistribute this Software in source and binary forms, with or without
00015  * modification, provided that redistributions of source code must retain this
00016  * notice. You may not view, use, disclose, copy or distribute this file or
00017  * any information contained herein except pursuant to this license grant from
00018  * Synopsys. If you do not agree with this notice, including the disclaimer
00019  * below, then you are not authorized to use the Software.
00020  *
00021  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
00022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
00025  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00027  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00031  * DAMAGE.
00032  * ========================================================================== */
00033 
00034 #include "dwc_os.h"
00035 #include "dwc_otg_regs.h"
00036 #include "dwc_otg_cil.h"
00037 #include "dwc_otg_adp.h"
00038 
00046 void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
00047 {
00048         adpctl_data_t adpctl;
00049 
00050         adpctl.d32 = value;
00051         adpctl.b.ar = 0x2;
00052 
00053         DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
00054 
00055         while (adpctl.b.ar) {
00056                 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
00057         }
00058 
00059 }
00060 
00064 uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
00065 {
00066         adpctl_data_t adpctl;
00067 
00068         adpctl.d32 = 0;
00069         adpctl.b.ar = 0x1;
00070 
00071         DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
00072 
00073         while (adpctl.b.ar) {
00074                 adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
00075         }
00076 
00077         return adpctl.d32;
00078 }
00079 
00083 uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
00084 {
00085         adpctl_data_t adpctl;
00086 
00087         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00088         adpctl.b.adp_tmout_int = 0;
00089         adpctl.b.adp_prb_int = 0;
00090         adpctl.b.adp_tmout_int = 0;
00091                 
00092         return adpctl.d32;
00093 }
00094 
00098 void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
00099                             uint32_t set)
00100 {
00101         dwc_otg_adp_write_reg(core_if,
00102                               (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
00103 }
00104 
00105 static void adp_sense_timeout(void *ptr)
00106 {
00107         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
00108         core_if->adp.sense_timer_started = 0;
00109         DWC_PRINTF("ADP SENSE TIMEOUT\n");
00110         if (core_if->adp_enable) {
00111                 dwc_otg_adp_sense_stop(core_if);
00112                 dwc_otg_adp_probe_start(core_if);
00113         }
00114 }
00115 
00119 static void adp_vbuson_timeout(void *ptr)
00120 {
00121         gpwrdn_data_t gpwrdn;
00122         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
00123         hprt0_data_t hprt0 = {.d32 = 0 };
00124         pcgcctl_data_t pcgcctl = {.d32 = 0 };
00125         DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
00126         if (core_if) {
00127                 core_if->adp.vbuson_timer_started = 0;
00128                 /* Turn off vbus */
00129                 hprt0.b.prtpwr = 1;
00130                 DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
00131                 gpwrdn.d32 = 0;
00132 
00133                 /* Power off the core */
00134                 if (core_if->power_down == 2) {
00135                         /* Enable Wakeup Logic */
00136 //                      gpwrdn.b.wkupactiv = 1;
00137                         gpwrdn.b.pmuactv = 0;
00138                         gpwrdn.b.pwrdnrstn = 1;
00139                         gpwrdn.b.pwrdnclmp = 1;
00140                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
00141                                          gpwrdn.d32);
00142 
00143                         /* Suspend the Phy Clock */
00144                         pcgcctl.b.stoppclk = 1;
00145                         DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
00146 
00147                         /* Switch on VDD */
00148 //                      gpwrdn.b.wkupactiv = 1;
00149                         gpwrdn.b.pmuactv = 1;
00150                         gpwrdn.b.pwrdnrstn = 1;
00151                         gpwrdn.b.pwrdnclmp = 1;
00152                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
00153                                          gpwrdn.d32);
00154                 } else {
00155                         /* Enable Power Down Logic */
00156                         gpwrdn.b.pmuintsel = 1;
00157                         gpwrdn.b.pmuactv = 1;
00158                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00159                 }
00160 
00161                 /* Power off the core */
00162                 if (core_if->power_down == 2) {
00163                         gpwrdn.d32 = 0;
00164                         gpwrdn.b.pwrdnswtch = 1;
00165                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
00166                                          gpwrdn.d32, 0);
00167                 }
00168 
00169                 /* Unmask SRP detected interrupt from Power Down Logic */
00170                 gpwrdn.d32 = 0;
00171                 gpwrdn.b.srp_det_msk = 1;
00172                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00173 
00174                 dwc_otg_adp_probe_start(core_if);
00175                 dwc_otg_dump_global_registers(core_if);
00176                 dwc_otg_dump_host_registers(core_if);
00177         }
00178 
00179 }
00180 
00187 void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
00188 {
00189         core_if->adp.vbuson_timer_started = 1;
00190         if (core_if->adp.vbuson_timer)
00191         {
00192                 DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
00193                 /* 1.1 secs + 60ms necessary for cil_hcd_start*/
00194                 DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
00195         } else {
00196                 DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
00197         }
00198 }
00199 
00200 #if 0
00201 
00205 static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
00206 {
00207         int i;
00208         gahbcfg_data_t ahbcfg = {.d32 = 0 };
00209 
00210         /* Mask Host Interrupts */
00211 
00212         /* Clear and disable HCINTs */
00213         for (i = 0; i < core_if->core_params->host_channels; i++) {
00214                 DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
00215                 DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
00216 
00217         }
00218 
00219         /* Clear and disable HAINT */
00220         DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
00221         DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
00222 
00223         /* Mask Device Interrupts */
00224         if (!core_if->multiproc_int_enable) {
00225                 /* Clear and disable IN Endpoint interrupts */
00226                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
00227                 for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
00228                         DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
00229                                         diepint, 0xFFFFFFFF);
00230                 }
00231 
00232                 /* Clear and disable OUT Endpoint interrupts */
00233                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
00234                 for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
00235                         DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
00236                                         doepint, 0xFFFFFFFF);
00237                 }
00238 
00239                 /* Clear and disable DAINT */
00240                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
00241                                 0xFFFFFFFF);
00242                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
00243         } else {
00244                 for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
00245                         DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
00246                                         diepeachintmsk[i], 0);
00247                         DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
00248                                         diepint, 0xFFFFFFFF);
00249                 }
00250 
00251                 for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
00252                         DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
00253                                         doepeachintmsk[i], 0);
00254                         DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
00255                                         doepint, 0xFFFFFFFF);
00256                 }
00257 
00258                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
00259                                 0);
00260                 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
00261                                 0xFFFFFFFF);
00262 
00263         }
00264 
00265         /* Disable interrupts */
00266         ahbcfg.b.glblintrmsk = 1;
00267         DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
00268 
00269         /* Disable all interrupts. */
00270         DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
00271 
00272         /* Clear any pending interrupts */
00273         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
00274 
00275         /* Clear any pending OTG Interrupts */
00276         DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
00277 }
00278 
00283 static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
00284 {
00285         gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
00286 
00287         DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
00288 }
00289 #endif
00290 
00296 uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
00297 {
00298 
00299         adpctl_data_t adpctl = {.d32 = 0};
00300         gpwrdn_data_t gpwrdn;
00301 #if 0
00302         adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
00303                                                                 .b.adp_sns_int = 1, b.adp_tmout_int};
00304 #endif
00305         dwc_otg_disable_global_interrupts(core_if);
00306         DWC_PRINTF("ADP Probe Start\n");
00307         core_if->adp.probe_enabled = 1;
00308 
00309         adpctl.b.adpres = 1;
00310         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00311 
00312         while (adpctl.b.adpres) {
00313                 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00314         }
00315 
00316         adpctl.d32 = 0;
00317         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00318 
00319         /* In Host mode unmask SRP detected interrupt */
00320         gpwrdn.d32 = 0;
00321         gpwrdn.b.sts_chngint_msk = 1;
00322         if (!gpwrdn.b.idsts) {
00323                 gpwrdn.b.srp_det_msk = 1;
00324         }
00325         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00326 
00327         adpctl.b.adp_tmout_int_msk = 1;
00328         adpctl.b.adp_prb_int_msk = 1;
00329         adpctl.b.prb_dschg = 1;
00330         adpctl.b.prb_delta = 1;
00331         adpctl.b.prb_per = 1;
00332         adpctl.b.adpen = 1;
00333         adpctl.b.enaprb = 1;
00334 
00335         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00336         DWC_PRINTF("ADP Probe Finish\n");
00337         return 0;
00338 }
00339 
00346 void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
00347 {
00348         core_if->adp.sense_timer_started = 1;
00349         DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
00350 }
00351 
00357 uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
00358 {
00359         adpctl_data_t adpctl;
00360 
00361         DWC_PRINTF("ADP Sense Start\n");
00362 
00363         /* Unmask ADP sense interrupt and mask all other from the core */
00364         adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
00365         adpctl.b.adp_sns_int_msk = 1;
00366         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00367         dwc_otg_disable_global_interrupts(core_if); // vahrama 
00368 
00369         /* Set ADP reset bit*/
00370         adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
00371         adpctl.b.adpres = 1;
00372         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00373 
00374         while (adpctl.b.adpres) {
00375                 adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00376         }
00377 
00378         adpctl.b.adpres = 0;
00379         adpctl.b.adpen = 1;
00380         adpctl.b.enasns = 1;
00381         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00382 
00383         dwc_otg_adp_sense_timer_start(core_if);
00384 
00385         return 0;
00386 }
00387 
00393 uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
00394 {
00395 
00396         adpctl_data_t adpctl;
00397         DWC_PRINTF("Stop ADP probe\n");
00398         core_if->adp.probe_enabled = 0;
00399         core_if->adp.probe_counter = 0;
00400         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00401 
00402         adpctl.b.adpen = 0;
00403         adpctl.b.adp_prb_int = 1;
00404         adpctl.b.adp_tmout_int = 1;
00405         adpctl.b.adp_sns_int = 1;
00406         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00407 
00408         return 0;
00409 }
00410 
00416 uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
00417 {
00418         adpctl_data_t adpctl;
00419 
00420         core_if->adp.sense_enabled = 0;
00421 
00422         adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
00423         adpctl.b.enasns = 0;
00424         adpctl.b.adp_sns_int = 1;
00425         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00426 
00427         return 0;
00428 }
00429 
00437 void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
00438 {
00439         hprt0_data_t hprt0 = {.d32 = 0 };
00440         hprt0.d32 = dwc_otg_read_hprt0(core_if);
00441         DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
00442 
00443         if (hprt0.b.prtpwr == 0) {
00444                 hprt0.b.prtpwr = 1;
00445                 //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
00446         }
00447         
00448         dwc_otg_adp_vbuson_timer_start(core_if);
00449 }
00450 
00458 void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
00459 {
00460         gpwrdn_data_t gpwrdn;
00461 
00462         DWC_PRINTF("ADP Initial Start\n");
00463         core_if->adp.adp_started = 1;
00464 
00465         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
00466         dwc_otg_disable_global_interrupts(core_if);
00467         if (is_host) {
00468                 DWC_PRINTF("HOST MODE\n");
00469                 /* Enable Power Down Logic Interrupt*/
00470                 gpwrdn.d32 = 0;
00471                 gpwrdn.b.pmuintsel = 1;
00472                 gpwrdn.b.pmuactv = 1;
00473                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00474                 /* Initialize first ADP probe to obtain Ramp Time value */
00475                 core_if->adp.initial_probe = 1;
00476                 dwc_otg_adp_probe_start(core_if);
00477         } else {
00478                 gotgctl_data_t gotgctl;
00479                 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
00480                 DWC_PRINTF("DEVICE MODE\n");
00481                 if (gotgctl.b.bsesvld == 0) {
00482                         /* Enable Power Down Logic Interrupt*/
00483                         gpwrdn.d32 = 0;
00484                         DWC_PRINTF("VBUS is not valid - start ADP probe\n");
00485                         gpwrdn.b.pmuintsel = 1;
00486                         gpwrdn.b.pmuactv = 1;
00487                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
00488                         core_if->adp.initial_probe = 1;
00489                         dwc_otg_adp_probe_start(core_if);
00490                 } else {
00491                         DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
00492                         core_if->op_state = B_PERIPHERAL;
00493                         dwc_otg_core_init(core_if);
00494                         dwc_otg_enable_global_interrupts(core_if);
00495                         cil_pcd_start(core_if);
00496                         dwc_otg_dump_global_registers(core_if);
00497                         dwc_otg_dump_dev_registers(core_if);
00498                 }
00499         }
00500 }
00501 
00502 void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
00503 {
00504         core_if->adp.adp_started = 0;
00505         core_if->adp.initial_probe = 0;
00506         core_if->adp.probe_timer_values[0] = -1;
00507         core_if->adp.probe_timer_values[1] = -1;
00508         core_if->adp.probe_enabled = 0;
00509         core_if->adp.sense_enabled = 0;
00510         core_if->adp.sense_timer_started = 0;
00511         core_if->adp.vbuson_timer_started = 0;
00512         core_if->adp.probe_counter = 0;
00513         core_if->adp.gpwrdn = 0;
00514         core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
00515         /* Initialize timers */
00516         core_if->adp.sense_timer =
00517             DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
00518         core_if->adp.vbuson_timer =
00519             DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
00520         if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
00521         {
00522                 DWC_ERROR("Could not allocate memory for ADP timers\n");
00523         }
00524 }
00525 
00526 void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
00527 {
00528         gpwrdn_data_t gpwrdn = { .d32 = 0 };
00529         gpwrdn.b.pmuintsel = 1;
00530         gpwrdn.b.pmuactv = 1;
00531         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00532 
00533         if (core_if->adp.probe_enabled)         
00534                 dwc_otg_adp_probe_stop(core_if);
00535         if (core_if->adp.sense_enabled)         
00536                 dwc_otg_adp_sense_stop(core_if);
00537         if (core_if->adp.sense_timer_started)           
00538                 DWC_TIMER_CANCEL(core_if->adp.sense_timer);
00539         if (core_if->adp.vbuson_timer_started)          
00540                 DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
00541         DWC_TIMER_FREE(core_if->adp.sense_timer);
00542         DWC_TIMER_FREE(core_if->adp.vbuson_timer);
00543 }
00544 
00548 
00551 static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
00552 {
00553         if (core_if->adp.probe_timer_values[0] == -1) {
00554                 core_if->adp.probe_timer_values[0] = val;
00555                 core_if->adp.probe_timer_values[1] = -1;
00556                 return 1;
00557         } else {
00558                 core_if->adp.probe_timer_values[1] =
00559                     core_if->adp.probe_timer_values[0];
00560                 core_if->adp.probe_timer_values[0] = val;
00561                 return 0;
00562         }
00563 }
00564 
00568 static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
00569 {
00570         uint32_t diff;
00571         if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
00572                         diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
00573         else
00574                         diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];           
00575         if(diff < 2) {
00576                 return 0;
00577         } else {
00578                 return 1;
00579         }
00580 }
00581 
00585 static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
00586                                                  uint32_t val)
00587 {
00588         adpctl_data_t adpctl = {.d32 = 0 };
00589         gpwrdn_data_t gpwrdn, temp;
00590         adpctl.d32 = val;
00591 
00592         temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00593         core_if->adp.probe_counter++;
00594         core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00595         if (adpctl.b.rtim == 0 && !temp.b.idsts){
00596                 DWC_PRINTF("RTIM value is 0\n");        
00597                 goto exit;
00598         }
00599         if (set_timer_value(core_if, adpctl.b.rtim) &&
00600             core_if->adp.initial_probe) {
00601                 core_if->adp.initial_probe = 0;
00602                 dwc_otg_adp_probe_stop(core_if);
00603                 gpwrdn.d32 = 0;
00604                 gpwrdn.b.pmuactv = 1;
00605                 gpwrdn.b.pmuintsel = 1;
00606                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00607                 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
00608 
00609                 /* check which value is for device mode and which for Host mode */
00610                 if (!temp.b.idsts) {    /* considered host mode value is 0 */
00611                         /*
00612                          * Turn on VBUS after initial ADP probe.
00613                          */
00614                         core_if->op_state = A_HOST;
00615                         dwc_otg_enable_global_interrupts(core_if);
00616                         DWC_SPINUNLOCK(core_if->lock);
00617                         cil_hcd_start(core_if);
00618                         dwc_otg_adp_turnon_vbus(core_if);
00619                         DWC_SPINLOCK(core_if->lock);
00620                 } else {
00621                         /*
00622                          * Initiate SRP after initial ADP probe.
00623                          */
00624                         dwc_otg_enable_global_interrupts(core_if);
00625                         dwc_otg_initiate_srp(core_if);
00626                 }
00627         } else if (core_if->adp.probe_counter > 2){
00628                 gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00629                 if (compare_timer_values(core_if)) {
00630                         DWC_PRINTF("Difference in timer values !!! \n");
00631 //                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
00632                         dwc_otg_adp_probe_stop(core_if);
00633 
00634                         /* Power on the core */
00635                         if (core_if->power_down == 2) {
00636                                 gpwrdn.b.pwrdnswtch = 1;
00637                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00638                                                  gpwrdn, 0, gpwrdn.d32);
00639                         }
00640 
00641                         /* check which value is for device mode and which for Host mode */
00642                         if (!temp.b.idsts) {    /* considered host mode value is 0 */
00643                                 /* Disable Interrupt from Power Down Logic */
00644                                 gpwrdn.d32 = 0;
00645                                 gpwrdn.b.pmuintsel = 1;
00646                                 gpwrdn.b.pmuactv = 1;
00647                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00648                                                  gpwrdn, gpwrdn.d32, 0);
00649 
00650                                 /*
00651                                  * Initialize the Core for Host mode.
00652                                  */
00653                                 core_if->op_state = A_HOST;
00654                                 dwc_otg_core_init(core_if);
00655                                 dwc_otg_enable_global_interrupts(core_if);
00656                                 cil_hcd_start(core_if);
00657                         } else {
00658                                 gotgctl_data_t gotgctl;
00659                                 /* Mask SRP detected interrupt from Power Down Logic */
00660                                 gpwrdn.d32 = 0;
00661                                 gpwrdn.b.srp_det_msk = 1;
00662                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00663                                                  gpwrdn, gpwrdn.d32, 0);
00664 
00665                                 /* Disable Power Down Logic */
00666                                 gpwrdn.d32 = 0;
00667                                 gpwrdn.b.pmuintsel = 1;
00668                                 gpwrdn.b.pmuactv = 1;
00669                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00670                                                  gpwrdn, gpwrdn.d32, 0);
00671 
00672                                 /*
00673                                  * Initialize the Core for Device mode.
00674                                  */
00675                                 core_if->op_state = B_PERIPHERAL;
00676                                 dwc_otg_core_init(core_if);
00677                                 dwc_otg_enable_global_interrupts(core_if);
00678                                 cil_pcd_start(core_if);
00679 
00680                                 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
00681                                 if (!gotgctl.b.bsesvld) {
00682                                         dwc_otg_initiate_srp(core_if);
00683                                 }
00684                         }
00685                 }
00686                 if (core_if->power_down == 2) {
00687                         if (gpwrdn.b.bsessvld) {
00688                                 /* Mask SRP detected interrupt from Power Down Logic */
00689                                 gpwrdn.d32 = 0;
00690                                 gpwrdn.b.srp_det_msk = 1;
00691                                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00692                                 
00693                                 /* Disable Power Down Logic */
00694                                 gpwrdn.d32 = 0;
00695                                 gpwrdn.b.pmuactv = 1;
00696                                 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
00697 
00698                                 /*
00699                                  * Initialize the Core for Device mode.
00700                                  */
00701                                 core_if->op_state = B_PERIPHERAL;
00702                                 dwc_otg_core_init(core_if);
00703                                 dwc_otg_enable_global_interrupts(core_if);
00704                                 cil_pcd_start(core_if);
00705                         }
00706                 }
00707         }
00708 exit:
00709         /* Clear interrupt */
00710         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00711         adpctl.b.adp_prb_int = 1;
00712         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00713 
00714         return 0;
00715 }
00716 
00720 static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
00721 {
00722         adpctl_data_t adpctl;
00723         /* Stop ADP Sense timer */
00724         DWC_TIMER_CANCEL(core_if->adp.sense_timer);
00725 
00726         /* Restart ADP Sense timer */
00727         dwc_otg_adp_sense_timer_start(core_if);
00728         
00729         /* Clear interrupt */
00730         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00731         adpctl.b.adp_sns_int = 1;
00732         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00733 
00734         return 0;
00735 }
00736 
00740 static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
00741                                                  uint32_t val)
00742 {
00743         adpctl_data_t adpctl = {.d32 = 0 };
00744         adpctl.d32 = val;
00745         set_timer_value(core_if, adpctl.b.rtim);
00746         
00747         /* Clear interrupt */
00748         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00749         adpctl.b.adp_tmout_int = 1;
00750         dwc_otg_adp_write_reg(core_if, adpctl.d32);
00751 
00752         return 0;
00753 }
00754 
00759 int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
00760 {
00761         int retval = 0;
00762         adpctl_data_t adpctl = {.d32 = 0};
00763 
00764         adpctl.d32 = dwc_otg_adp_read_reg(core_if);
00765         DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
00766 
00767         if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
00768                 DWC_PRINTF("ADP Sense interrupt\n");
00769                 retval |= dwc_otg_adp_handle_sns_intr(core_if);
00770         }
00771         if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
00772                 DWC_PRINTF("ADP timeout interrupt\n");
00773                 retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
00774         }
00775         if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
00776                 DWC_PRINTF("ADP Probe interrupt\n");
00777                 adpctl.b.adp_prb_int = 1;       
00778                 retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
00779         }
00780 
00781 //      dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
00782         //dwc_otg_adp_write_reg(core_if, adpctl.d32);
00783         DWC_PRINTF("RETURN FROM ADP ISR\n");
00784 
00785         return retval;
00786 }
00787 
00792 int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
00793 {
00794 
00795 #ifndef DWC_HOST_ONLY
00796         hprt0_data_t hprt0;
00797         gpwrdn_data_t gpwrdn;
00798         DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
00799 
00800         gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
00801         /* check which value is for device mode and which for Host mode */
00802         if (!gpwrdn.b.idsts) {  /* considered host mode value is 0 */
00803                 DWC_PRINTF("SRP: Host mode\n");
00804 
00805                 if (core_if->adp_enable) {
00806                         dwc_otg_adp_probe_stop(core_if);
00807 
00808                         /* Power on the core */
00809                         if (core_if->power_down == 2) {
00810                                 gpwrdn.b.pwrdnswtch = 1;
00811                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00812                                                  gpwrdn, 0, gpwrdn.d32);
00813                         }
00814 
00815                         core_if->op_state = A_HOST;
00816                         dwc_otg_core_init(core_if);
00817                         dwc_otg_enable_global_interrupts(core_if);
00818                         cil_hcd_start(core_if);
00819                 }
00820 
00821                 /* Turn on the port power bit. */
00822                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
00823                 hprt0.b.prtpwr = 1;
00824                 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
00825 
00826                 /* Start the Connection timer. So a message can be displayed
00827                  * if connect does not occur within 10 seconds. */
00828                 cil_hcd_session_start(core_if);
00829         } else {
00830                 DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
00831                 if (core_if->adp_enable) {
00832                         dwc_otg_adp_probe_stop(core_if);
00833 
00834                         /* Power on the core */
00835                         if (core_if->power_down == 2) {
00836                                 gpwrdn.b.pwrdnswtch = 1;
00837                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
00838                                                  gpwrdn, 0, gpwrdn.d32);
00839                         }
00840 
00841                         gpwrdn.d32 = 0;
00842                         gpwrdn.b.pmuactv = 0;
00843                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
00844                                          gpwrdn.d32);
00845 
00846                         core_if->op_state = B_PERIPHERAL;
00847                         dwc_otg_core_init(core_if);
00848                         dwc_otg_enable_global_interrupts(core_if);
00849                         cil_pcd_start(core_if);
00850                 }
00851         }
00852 #endif
00853         return 1;
00854 }

Generated on Thu Oct 27 03:56:37 2011 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.3.9.1