00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 #ifndef DWC_DEVICE_ONLY
00034 
00042 #include "dwc_otg_hcd.h"
00043 #include "dwc_otg_regs.h"
00044                 
00045 dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
00046 {
00047         return dwc_alloc(sizeof(dwc_otg_hcd_t));
00048 }
00049 
00054 void dwc_otg_hcd_connect_timeout(void *ptr)
00055 {
00056         DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
00057         DWC_PRINTF("Connect Timeout\n");
00058         __DWC_ERROR("Device Not Connected/Responding\n");
00059 }
00060 
00061 #ifdef DEBUG
00062 static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
00063 {
00064         if (qh->channel != NULL) {
00065                 dwc_hc_t *hc = qh->channel;
00066                 dwc_list_link_t *item;
00067                 dwc_otg_qh_t *qh_item;
00068                 int num_channels = hcd->core_if->core_params->host_channels;
00069                 int i;
00070 
00071                 dwc_otg_hc_regs_t *hc_regs;
00072                 hcchar_data_t hcchar;
00073                 hcsplt_data_t hcsplt;
00074                 hctsiz_data_t hctsiz;
00075                 uint32_t hcdma;
00076 
00077                 hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
00078                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
00079                 hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
00080                 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
00081                 hcdma = dwc_read_reg32(&hc_regs->hcdma);
00082 
00083                 DWC_PRINTF("  Assigned to channel %p:\n", hc);
00084                 DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
00085                            hcsplt.d32);
00086                 DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
00087                            hcdma);
00088                 DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
00089                            hc->dev_addr, hc->ep_num, hc->ep_is_in);
00090                 DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
00091                 DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
00092                 DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
00093                 DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
00094                 DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
00095                 DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
00096                 DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
00097                 DWC_PRINTF("    qh: %p\n", hc->qh);
00098                 DWC_PRINTF("  NP inactive sched:\n");
00099                 DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
00100                         qh_item =
00101                             DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
00102                         DWC_PRINTF("    %p\n", qh_item);
00103                 }
00104                 DWC_PRINTF("  NP active sched:\n");
00105                 DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
00106                         qh_item =
00107                             DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
00108                         DWC_PRINTF("    %p\n", qh_item);
00109                 }
00110                 DWC_PRINTF("  Channels: \n");
00111                 for (i = 0; i < num_channels; i++) {
00112                         dwc_hc_t *hc = hcd->hc_ptr_array[i];
00113                         DWC_PRINTF("    %2d: %p\n", i, hc);
00114                 }
00115         }
00116 }
00117 #endif                          
00118 
00123 static void hcd_start_func(void *_vp)
00124 {
00125         dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
00126 
00127         DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
00128         if (hcd) {
00129                 hcd->fops->start(hcd);
00130         }
00131 }
00132 
00133 static void del_xfer_timers(dwc_otg_hcd_t * hcd)
00134 {
00135 #ifdef DEBUG
00136         int i;
00137         int num_channels = hcd->core_if->core_params->host_channels;
00138         for (i = 0; i < num_channels; i++) {
00139                 DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
00140         }
00141 #endif
00142 }
00143 
00144 static void del_timers(dwc_otg_hcd_t * hcd)
00145 {
00146         del_xfer_timers(hcd);
00147         DWC_TIMER_CANCEL(hcd->conn_timer);
00148 }
00149 
00154 static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
00155 {
00156         dwc_list_link_t *qh_item;
00157         dwc_otg_qh_t *qh;
00158         dwc_otg_qtd_t *qtd, *qtd_tmp;
00159 
00160         DWC_LIST_FOREACH(qh_item, qh_list) {
00161                 qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
00162                 DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
00163                                          &qh->qtd_list, qtd_list_entry) {
00164                         qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
00165                         if (qtd->urb != NULL) {
00166                                 hcd->fops->complete(hcd, qtd->urb->priv,
00167                                                     qtd->urb,
00168                                                     -DWC_E_TIMEOUT);
00169                                 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
00170                         }
00171 
00172                 }
00173         }
00174 }
00175 
00182 static void kill_all_urbs(dwc_otg_hcd_t * hcd)
00183 {
00184         kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
00185         kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
00186         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
00187         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
00188         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
00189         kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
00190 }
00191 
00198 static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
00199 {
00200         DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000  );
00201 }
00202 
00208 static int32_t dwc_otg_hcd_session_start_cb(void *p)
00209 {
00210         dwc_otg_hcd_t *dwc_otg_hcd;
00211         DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
00212         dwc_otg_hcd = p;
00213         dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
00214         return 1;
00215 }
00216 
00223 static int32_t dwc_otg_hcd_start_cb(void *p)
00224 {
00225         dwc_otg_hcd_t *dwc_otg_hcd = p;
00226         dwc_otg_core_if_t *core_if;
00227         hprt0_data_t hprt0;
00228 
00229         core_if = dwc_otg_hcd->core_if;
00230 
00231         if (core_if->op_state == B_HOST) {
00232                 
00233 
00234 
00235 
00236 
00237                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
00238                 hprt0.b.prtrst = 1;
00239                 dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
00240         }
00241         DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
00242                                    hcd_start_func, dwc_otg_hcd, 50,
00243                                    "start hcd");
00244 
00245         return 1;
00246 }
00247 
00253 static int32_t dwc_otg_hcd_disconnect_cb(void *p)
00254 {
00255         gintsts_data_t intr;
00256         dwc_otg_hcd_t *dwc_otg_hcd = p;
00257 
00258         
00259 
00260 
00261         dwc_otg_hcd->flags.b.port_connect_status_change = 1;
00262         dwc_otg_hcd->flags.b.port_connect_status = 0;
00263 
00264         
00265 
00266 
00267 
00268 
00269         intr.d32 = 0;
00270         intr.b.nptxfempty = 1;
00271         intr.b.ptxfempty = 1;
00272         intr.b.hcintr = 1;
00273         dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
00274                          intr.d32, 0);
00275         dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
00276                          intr.d32, 0);
00277 
00278         del_timers(dwc_otg_hcd);
00279 
00280         
00281 
00282 
00283 
00284 
00285         if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
00286                 if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
00287                         hprt0_data_t hprt0 = {.d32 = 0 };
00288                         DWC_PRINTF("Disconnect: PortPower off\n");
00289                         hprt0.b.prtpwr = 0;
00290                         dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0,
00291                                         hprt0.d32);
00292                 }
00293 
00294                 dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
00295         }
00296 
00297         
00298         kill_all_urbs(dwc_otg_hcd);
00299 
00300         if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
00301                 
00302                 int num_channels;
00303                 int i;
00304                 dwc_hc_t *channel;
00305                 dwc_otg_hc_regs_t *hc_regs;
00306                 hcchar_data_t hcchar;
00307 
00308                 num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
00309 
00310                 if (!dwc_otg_hcd->core_if->dma_enable) {
00311                         
00312                         for (i = 0; i < num_channels; i++) {
00313                                 channel = dwc_otg_hcd->hc_ptr_array[i];
00314                                 if (DWC_CIRCLEQ_EMPTY_ENTRY
00315                                     (channel, hc_list_entry)) {
00316                                         hc_regs =
00317                                             dwc_otg_hcd->core_if->host_if->
00318                                             hc_regs[i];
00319                                         hcchar.d32 =
00320                                             dwc_read_reg32(&hc_regs->hcchar);
00321                                         if (hcchar.b.chen) {
00322                                                 hcchar.b.chen = 0;
00323                                                 hcchar.b.chdis = 1;
00324                                                 hcchar.b.epdir = 0;
00325                                                 dwc_write_reg32(&hc_regs->
00326                                                                 hcchar,
00327                                                                 hcchar.d32);
00328                                         }
00329                                 }
00330                         }
00331                 }
00332 
00333                 for (i = 0; i < num_channels; i++) {
00334                         channel = dwc_otg_hcd->hc_ptr_array[i];
00335                         if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
00336                                 hc_regs =
00337                                     dwc_otg_hcd->core_if->host_if->hc_regs[i];
00338                                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
00339                                 if (hcchar.b.chen) {
00340                                         
00341                                         hcchar.b.chdis = 1;
00342                                         dwc_write_reg32(&hc_regs->hcchar,
00343                                                         hcchar.d32);
00344                                 }
00345 
00346                                 dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
00347                                                    channel);
00348                                 DWC_CIRCLEQ_INSERT_TAIL(&dwc_otg_hcd->
00349                                                         free_hc_list, channel,
00350                                                         hc_list_entry);
00351                                 
00352 
00353 
00354 
00355                      
00356                                 channel->qh = NULL;                     
00357                         }
00358                 }
00359         }
00360 
00361         if (dwc_otg_hcd->fops->disconnect) {
00362                 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
00363         }
00364 
00365         return 1;
00366 }
00367 
00373 static int32_t dwc_otg_hcd_stop_cb(void *p)
00374 {
00375         dwc_otg_hcd_t *dwc_otg_hcd = p;
00376 
00377         DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
00378         dwc_otg_hcd_stop(dwc_otg_hcd);
00379         return 1;
00380 }
00381 
00382 #ifdef CONFIG_USB_DWC_OTG_LPM
00383 
00388 static int dwc_otg_hcd_sleep_cb(void *p)
00389 {
00390         dwc_otg_hcd_t *hcd = p;
00391 
00392         dwc_otg_hcd_free_hc_from_lpm(hcd);
00393 
00394         return 0;
00395 }
00396 #endif
00397 
00403 static int dwc_otg_hcd_rem_wakeup_cb(void *p)
00404 {
00405         dwc_otg_hcd_t *hcd = p;
00406 
00407         if (hcd->core_if->lx_state == DWC_OTG_L2) {
00408                 hcd->flags.b.port_suspend_change = 1;
00409         }
00410 #ifdef CONFIG_USB_DWC_OTG_LPM
00411         else {
00412                 hcd->flags.b.port_l1_change = 1;
00413         }
00414 #endif
00415         return 0;
00416 }
00417 
00422 void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
00423 {
00424         hprt0_data_t hprt0 = {.d32 = 0 };
00425 
00426         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
00427 
00428         
00429 
00430 
00431 
00432 
00433 
00434         
00435         dwc_otg_disable_host_interrupts(hcd->core_if);
00436 
00437         
00438         DWC_PRINTF("PortPower off\n");
00439         hprt0.b.prtpwr = 0;
00440         dwc_write_reg32(hcd->core_if->host_if->hprt0, hprt0.d32);
00441         dwc_mdelay(1);
00442 }
00443 
00444 int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
00445                             dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle)
00446 {
00447         uint64_t flags;
00448         int retval = 0;
00449         dwc_otg_qtd_t *qtd;
00450 
00451         if (!hcd->flags.b.port_connect_status) {
00452                 
00453                 return -DWC_E_NO_DEVICE;
00454         }
00455 
00456         qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb);
00457         if (qtd == NULL) {
00458                 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
00459                 return -DWC_E_NO_MEMORY;
00460         }
00461 
00462         retval =
00463             dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle);
00464         if (retval < 0) {
00465                 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
00466                           "Error status %d\n", retval);
00467                 dwc_otg_hcd_qtd_free(qtd);
00468         } else {
00469                 qtd->qh = *ep_handle;
00470         }
00471         
00472         if (hcd->core_if->dma_desc_enable && retval == 0) {
00473                 dwc_otg_transaction_type_e tr_type;     
00474                 if ((qtd->qh->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
00475                         
00476                         return 0;
00477                 }
00478                 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
00479                 tr_type = dwc_otg_hcd_select_transactions(hcd);
00480                 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
00481                         dwc_otg_hcd_queue_transactions(hcd, tr_type);
00482                 }
00483                 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
00484         }
00485 
00486         return retval;
00487 }
00488 
00489 int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
00490                             dwc_otg_hcd_urb_t * dwc_otg_urb)
00491 {
00492         uint64_t flags;
00493 
00494         dwc_otg_qh_t *qh;
00495         dwc_otg_qtd_t *urb_qtd;
00496 
00497         DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
00498         
00499         urb_qtd = dwc_otg_urb->qtd;
00500         qh = urb_qtd->qh;
00501 #ifdef DEBUG
00502         if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00503                 if (urb_qtd->in_process) {
00504                         dump_channel_info(hcd, qh);
00505                 }
00506         }
00507 #endif
00508         if (urb_qtd->in_process && qh->channel) {
00509                 
00510                 if (hcd->flags.b.port_connect_status) {
00511                         
00512 
00513 
00514 
00515 
00516 
00517 
00518                         dwc_otg_hc_halt(hcd->core_if, qh->channel,
00519                                         DWC_OTG_HC_XFER_URB_DEQUEUE);
00520                 }
00521         }
00522 
00523         
00524 
00525 
00526 
00527          
00528         if (!hcd->core_if->dma_desc_enable) {
00529                 uint8_t b = urb_qtd->in_process;        
00530                 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
00531                 if (b) {
00532                         dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
00533                         qh->channel = NULL;
00534                 } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
00535                         dwc_otg_hcd_qh_remove(hcd, qh);
00536                 }
00537         }
00538         else {
00539                 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
00540         }
00541         
00542         DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
00543 
00544         return 0;
00545 }
00546 
00547 int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
00548                                  int retry)
00549 {
00550         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
00551         int retval = 0;
00552         uint64_t flags;
00553 
00554         if (retry < 0) {
00555                 retval = -DWC_E_INVALID;
00556                 goto done;
00557         }
00558 
00559         if (!qh) {
00560                 goto done;
00561         }
00562 
00563         DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
00564         
00565         while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
00566                 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
00567                 retry--;
00568                 dwc_msleep(5);
00569                 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
00570         }
00571 
00572         dwc_otg_hcd_qh_remove(hcd, qh);
00573         
00574         DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
00575         
00576 
00577 
00578 
00579 
00580 
00581         dwc_otg_hcd_qh_free(hcd, qh);
00582 
00583       done:
00584         return retval;
00585 }
00586 
00590 static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
00591         .start = dwc_otg_hcd_start_cb,
00592         .stop = dwc_otg_hcd_stop_cb,
00593         .disconnect = dwc_otg_hcd_disconnect_cb,
00594         .session_start = dwc_otg_hcd_session_start_cb,
00595         .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
00596 #ifdef CONFIG_USB_DWC_OTG_LPM
00597         .sleep = dwc_otg_hcd_sleep_cb,
00598 #endif
00599         .p = 0,
00600 };
00601 
00605 static void reset_tasklet_func(void *data)
00606 {
00607         dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
00608         dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
00609         hprt0_data_t hprt0;
00610 
00611         DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
00612 
00613         hprt0.d32 = dwc_otg_read_hprt0(core_if);
00614         hprt0.b.prtrst = 1;
00615         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
00616         dwc_mdelay(60);
00617 
00618         hprt0.b.prtrst = 0;
00619         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
00620         dwc_otg_hcd->flags.b.port_reset_change = 1;
00621 }
00622 
00623 static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
00624 {
00625         dwc_list_link_t *item;
00626         dwc_otg_qh_t *qh;
00627 
00628         if (!qh_list->next) {
00629                 
00630                 return;
00631         }
00632 
00633         
00634         kill_urbs_in_qh_list(hcd, qh_list);
00635 
00636         DWC_LIST_FOREACH(item, qh_list) {
00637                 qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
00638                 dwc_otg_hcd_qh_remove_and_free(hcd, qh);
00639         }
00640 }
00641 
00646 static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
00647 {
00648         int i;
00649 
00650         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
00651 
00652         del_timers(dwc_otg_hcd);
00653 
00654         
00655         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
00656         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
00657         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
00658         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
00659         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
00660         qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
00661 
00662         
00663         for (i = 0; i < MAX_EPS_CHANNELS; i++) {
00664                 dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
00665 
00666 #ifdef DEBUG
00667                 if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
00668                         DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
00669                 }
00670 #endif
00671                 if (hc != NULL) {
00672                         DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
00673                                     i, hc);
00674                         dwc_free(hc);
00675                 }
00676         }
00677 
00678         if (dwc_otg_hcd->core_if->dma_enable) {
00679                 if (dwc_otg_hcd->status_buf_dma) {
00680                         dwc_dma_free(DWC_OTG_HCD_STATUS_BUF_SIZE,
00681                                      dwc_otg_hcd->status_buf,
00682                                      dwc_otg_hcd->status_buf_dma);
00683                 }
00684         } else if (dwc_otg_hcd->status_buf != NULL) {
00685                 dwc_free(dwc_otg_hcd->status_buf);
00686         }
00687         DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
00688         DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
00689         DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
00690         dwc_free(dwc_otg_hcd);
00691 }
00692 
00693 int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
00694 {
00695         int retval = 0;
00696         int num_channels;
00697         int i;
00698         dwc_hc_t *channel;
00699 
00700         hcd->lock = DWC_SPINLOCK_ALLOC();
00701 
00702         hcd->core_if = core_if;
00703         
00704         dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
00705                                            &hcd_cil_callbacks, hcd);
00706 
00707         
00708         DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
00709         DWC_LIST_INIT(&hcd->non_periodic_sched_active);
00710 
00711         
00712         DWC_LIST_INIT(&hcd->periodic_sched_inactive);
00713         DWC_LIST_INIT(&hcd->periodic_sched_ready);
00714         DWC_LIST_INIT(&hcd->periodic_sched_assigned);
00715         DWC_LIST_INIT(&hcd->periodic_sched_queued);
00716 
00717         
00718 
00719 
00720 
00721         DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
00722         num_channels = hcd->core_if->core_params->host_channels;
00723         DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
00724         for (i = 0; i < num_channels; i++) {
00725                 channel = dwc_alloc(sizeof(dwc_hc_t));
00726                 if (channel == NULL) {
00727                         retval = -DWC_E_NO_MEMORY;
00728                         DWC_ERROR("%s: host channel allocation failed\n",
00729                                   __func__);
00730                         dwc_otg_hcd_free(hcd);
00731                         goto out;
00732                 }
00733                 channel->hc_num = i;
00734                 hcd->hc_ptr_array[i] = channel;
00735 #ifdef DEBUG
00736                 hcd->core_if->hc_xfer_timer[i] =
00737                     DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
00738                                     &hcd->core_if->hc_xfer_info[i]);
00739 #endif
00740                 DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
00741                             channel);
00742         }
00743 
00744         
00745         hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
00746                                           dwc_otg_hcd_connect_timeout, 0);
00747 
00748         
00749         hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd);
00750 
00751         
00752 
00753 
00754 
00755 
00756 
00757         if (hcd->core_if->dma_enable) {
00758                 hcd->status_buf =
00759                     dwc_dma_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE,
00760                                   &hcd->status_buf_dma);
00761         } else {
00762                 hcd->status_buf = dwc_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE);
00763         }
00764         if (!hcd->status_buf) {
00765                 retval = -DWC_E_NO_MEMORY;
00766                 DWC_ERROR("%s: status_buf allocation failed\n", __func__);
00767                 dwc_otg_hcd_free(hcd);
00768                 goto out;
00769         }
00770 
00771         hcd->otg_port = 1;
00772         hcd->frame_list = NULL;
00773         hcd->frame_list_dma = 0;
00774 out:
00775         return retval;
00776 }
00777 
00778 void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
00779 {
00780         
00781         dwc_otg_disable_host_interrupts(hcd->core_if);
00782 
00783         dwc_otg_hcd_free(hcd);
00784 }
00785 
00789 static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
00790 {
00791         int num_channels;
00792         int i;
00793         dwc_hc_t *channel;
00794         dwc_hc_t *channel_tmp;
00795 
00796         hcd->flags.d32 = 0;
00797 
00798         hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
00799         hcd->non_periodic_channels = 0;
00800         hcd->periodic_channels = 0;
00801 
00802         
00803 
00804 
00805 
00806         DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
00807                                  &hcd->free_hc_list, hc_list_entry) {
00808                 DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
00809         }
00810 
00811         num_channels = hcd->core_if->core_params->host_channels;
00812         for (i = 0; i < num_channels; i++) {
00813                 channel = hcd->hc_ptr_array[i];
00814                 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
00815                                         hc_list_entry);
00816                 dwc_otg_hc_cleanup(hcd->core_if, channel);
00817         }
00818 
00819         
00820         dwc_otg_core_host_init(hcd->core_if);
00821 }
00822 
00832 static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
00833 {
00834         dwc_hc_t *hc;
00835         dwc_otg_qtd_t *qtd;
00836         dwc_otg_hcd_urb_t *urb;
00837         void* ptr = NULL;
00838 
00839         DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh);
00840 
00841         hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
00842 
00843         
00844         DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
00845 
00846         qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
00847         
00848         urb = qtd->urb;
00849         qh->channel = hc;
00850         
00851         qtd->in_process = 1;
00852 
00853         
00854 
00855 
00856 
00857         hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
00858         hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
00859         hc->speed = qh->dev_speed;
00860         hc->max_packet = dwc_max_packet(qh->maxp);
00861 
00862         hc->xfer_started = 0;
00863         hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
00864         hc->error_state = (qtd->error_count > 0);
00865         hc->halt_on_queue = 0;
00866         hc->halt_pending = 0;
00867         hc->requests = 0;
00868 
00869         
00870 
00871 
00872 
00873 
00874 
00875         hc->do_ping = qh->ping_state;
00876         hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
00877         hc->data_pid_start = qh->data_toggle;
00878         hc->multi_count = 1;
00879 
00880         if (hcd->core_if->dma_enable) {
00881                 hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
00882         
00883                 
00884                 if (((uint32_t)hc->xfer_buff & 0x3) && !hcd->core_if->dma_desc_enable) {
00885                         ptr = (uint8_t *) urb->buf + urb->actual_length;
00886                 }
00887         } else {
00888                 hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
00889         }
00890         hc->xfer_len = urb->length - urb->actual_length;
00891         hc->xfer_count = 0;
00892 
00893         
00894 
00895 
00896         hc->do_split = 0;
00897         if (qh->do_split) {
00898                 uint32_t hub_addr, port_addr;
00899                 hc->do_split = 1;
00900                 hc->xact_pos = qtd->isoc_split_pos;
00901                 hc->complete_split = qtd->complete_split;
00902                 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
00903                 hc->hub_addr = (uint8_t) hub_addr;
00904                 hc->port_addr = (uint8_t) port_addr;
00905         }
00906 
00907         switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
00908         case UE_CONTROL:
00909                 hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
00910                 switch (qtd->control_phase) {
00911                 case DWC_OTG_CONTROL_SETUP:
00912                         DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
00913                         hc->do_ping = 0;
00914                         hc->ep_is_in = 0;
00915                         hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
00916                         if (hcd->core_if->dma_enable) {
00917                                 hc->xfer_buff = (uint8_t *) urb->setup_dma;
00918                         } else {
00919                                 hc->xfer_buff = (uint8_t *) urb->setup_packet;
00920                         }
00921                         hc->xfer_len = 8;
00922                         ptr = NULL;
00923                         break;
00924                 case DWC_OTG_CONTROL_DATA:
00925                         DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
00926                         hc->data_pid_start = qtd->data_toggle;
00927                         break;
00928                 case DWC_OTG_CONTROL_STATUS:
00929                         
00930 
00931 
00932 
00933                         DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
00934                         if (urb->length == 0) {
00935                                 hc->ep_is_in = 1;
00936                         } else {
00937                                 hc->ep_is_in =
00938                                     dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
00939                         }
00940                         if (hc->ep_is_in) {
00941                                 hc->do_ping = 0;
00942                         }
00943                         
00944                         hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
00945 
00946                         hc->xfer_len = 0;
00947                         if (hcd->core_if->dma_enable) {
00948                                 hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
00949                         } else {
00950                                 hc->xfer_buff = (uint8_t *) hcd->status_buf;
00951                         }
00952                         ptr = NULL;
00953                         break;
00954                 }
00955                 break;
00956         case UE_BULK:
00957                 hc->ep_type = DWC_OTG_EP_TYPE_BULK;
00958                 break;
00959         case UE_INTERRUPT:
00960                 hc->ep_type = DWC_OTG_EP_TYPE_INTR;
00961                 break;
00962         case UE_ISOCHRONOUS:
00963                 {
00964                         struct dwc_otg_hcd_iso_packet_desc *frame_desc;
00965                         
00966                         hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
00967                         
00968                         if (hcd->core_if->dma_desc_enable)
00969                                 break;
00970                                 
00971                         frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
00972                         
00973                         frame_desc->status = 0;
00974                         
00975                         if (hcd->core_if->dma_enable) {
00976                                 hc->xfer_buff = (uint8_t *) urb->dma;
00977                         } else {
00978                                 hc->xfer_buff = (uint8_t *) urb->buf;
00979                         }
00980                         hc->xfer_buff +=
00981                             frame_desc->offset + qtd->isoc_split_offset;
00982                         hc->xfer_len =
00983                             frame_desc->length - qtd->isoc_split_offset;
00984 
00985                         
00986                         if (((uint32_t)hc->xfer_buff & 0x3) && hcd->core_if->dma_enable) {
00987                                 ptr = (uint8_t *) urb->buf + frame_desc->offset + qtd->isoc_split_offset;
00988                         }       
00989                         else
00990                             ptr = NULL;
00991                         
00992                         if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
00993                                 if (hc->xfer_len <= 188) {
00994                                         hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
00995                                 } else {
00996                                         hc->xact_pos =
00997                                             DWC_HCSPLIT_XACTPOS_BEGIN;
00998                                 }
00999                         }
01000                 }
01001                 break;
01002         }
01003              
01004         if (ptr) {
01005                 uint32_t buf_size;
01006                 if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
01007                         buf_size = hcd->core_if->core_params->max_transfer_size;
01008                 } else {                                
01009                         buf_size = 4096;
01010                 }
01011                 if (!qh->dw_align_buf) {
01012                         qh->dw_align_buf = dwc_dma_alloc(buf_size,
01013                                                          &qh->dw_align_buf_dma);
01014                         if (!qh->dw_align_buf) {
01015                                 DWC_ERROR("%s: Failed to allocate memory to handle "
01016                                           "non-dword aligned buffer case\n", __func__);
01017                                 return;
01018                         }
01019                 }
01020                 if (!hc->ep_is_in) {
01021                         dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
01022                 }
01023                 hc->align_buff = qh->dw_align_buf_dma;
01024         }
01025         else {
01026                 hc->align_buff = 0;
01027         }
01028 
01029         if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
01030             hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
01031                 
01032 
01033 
01034 
01035                 hc->multi_count = dwc_hb_mult(qh->maxp);
01036         }
01037         
01038         if (hcd->core_if->dma_desc_enable)
01039                 hc->desc_list_addr = qh->desc_list_dma;
01040         
01041         dwc_otg_hc_init(hcd->core_if, hc);
01042         hc->qh = qh;
01043 }
01044 
01045 
01055 dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
01056 {
01057         dwc_list_link_t *qh_ptr;
01058         dwc_otg_qh_t *qh;
01059         int num_channels;
01060         dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
01061 
01062 #ifdef DEBUG_SOF
01063         DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");
01064 #endif
01065 
01066         
01067         qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
01068 
01069         while (qh_ptr != &hcd->periodic_sched_ready &&
01070                !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
01071 
01072                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
01073                 assign_and_init_hc(hcd, qh);
01074 
01075                 
01076 
01077 
01078 
01079                 qh_ptr = DWC_LIST_NEXT(qh_ptr);
01080                 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
01081                                    &qh->qh_list_entry);
01082 
01083                 ret_val = DWC_OTG_TRANSACTION_PERIODIC;
01084         }
01085 
01086         
01087 
01088 
01089 
01090 
01091         qh_ptr = hcd->non_periodic_sched_inactive.next;
01092         num_channels = hcd->core_if->core_params->host_channels;
01093         while (qh_ptr != &hcd->non_periodic_sched_inactive &&
01094                (hcd->non_periodic_channels <
01095                 num_channels - hcd->periodic_channels) &&
01096                !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
01097 
01098                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
01099 
01100                 assign_and_init_hc(hcd, qh);
01101 
01102                 
01103 
01104 
01105 
01106                 qh_ptr = DWC_LIST_NEXT(qh_ptr);
01107                 DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
01108                                    &qh->qh_list_entry);
01109 
01110                 if (ret_val == DWC_OTG_TRANSACTION_NONE) {
01111                         ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
01112                 } else {
01113                         ret_val = DWC_OTG_TRANSACTION_ALL;
01114                 }
01115 
01116                 hcd->non_periodic_channels++;
01117         }
01118 
01119         return ret_val;
01120 }
01139 static int queue_transaction(dwc_otg_hcd_t * hcd,
01140                              dwc_hc_t * hc, uint16_t fifo_dwords_avail)
01141 {
01142         int retval;
01143 
01144         if (hcd->core_if->dma_enable) {
01145                 if (hcd->core_if->dma_desc_enable) {
01146                         if (!hc->xfer_started || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {       
01147                                 dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
01148                                 hc->qh->ping_state = 0;
01149                         }
01150                 }
01151                 else if (!hc->xfer_started) {
01152                         dwc_otg_hc_start_transfer(hcd->core_if, hc);
01153                         hc->qh->ping_state = 0;
01154                 }
01155                 retval = 0;
01156         } else if (hc->halt_pending) {
01157                 
01158                 retval = 0;
01159         } else if (hc->halt_on_queue) {
01160                 dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
01161                 retval = 0;
01162         } else if (hc->do_ping) {
01163                 if (!hc->xfer_started) {
01164                         dwc_otg_hc_start_transfer(hcd->core_if, hc);
01165                 }
01166                 retval = 0;
01167         } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
01168                 if ((fifo_dwords_avail * 4) >= hc->max_packet) {
01169                         if (!hc->xfer_started) {
01170                                 dwc_otg_hc_start_transfer(hcd->core_if, hc);
01171                                 retval = 1;
01172                         } else {
01173                                 retval =
01174                                     dwc_otg_hc_continue_transfer(hcd->core_if,
01175                                                                  hc);
01176                         }
01177                 } else {
01178                         retval = -1;
01179                 }
01180         } else {
01181                 if (!hc->xfer_started) {
01182                         dwc_otg_hc_start_transfer(hcd->core_if, hc);
01183                         retval = 1;
01184                 } else {
01185                         retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
01186                 }
01187         }
01188 
01189         return retval;
01190 }
01191 
01199 static void process_periodic_channels(dwc_otg_hcd_t * hcd)
01200 {
01201         hptxsts_data_t tx_status;
01202         dwc_list_link_t *qh_ptr;
01203         dwc_otg_qh_t *qh;
01204         int status;
01205         int no_queue_space = 0;
01206         int no_fifo_space = 0;
01207 
01208         dwc_otg_host_global_regs_t *host_regs;
01209         host_regs = hcd->core_if->host_if->host_global_regs;
01210 
01211         DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
01212 #ifdef DEBUG
01213         tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts);
01214         DWC_DEBUGPL(DBG_HCDV,
01215                     "  P Tx Req Queue Space Avail (before queue): %d\n",
01216                     tx_status.b.ptxqspcavail);
01217         DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
01218                     tx_status.b.ptxfspcavail);
01219 #endif
01220 
01221         qh_ptr = hcd->periodic_sched_assigned.next;
01222         while (qh_ptr != &hcd->periodic_sched_assigned) {
01223                 tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts);
01224                 if (tx_status.b.ptxqspcavail == 0) {
01225                         no_queue_space = 1;
01226                         break;
01227                 }
01228 
01229                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
01230 
01231                 
01232 
01233 
01234 
01235 
01236                 if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
01237                         hcd->core_if->queuing_high_bandwidth = 1;
01238                 }
01239                 status =
01240                     queue_transaction(hcd, qh->channel,
01241                                       tx_status.b.ptxfspcavail);
01242                 if (status < 0) {
01243                         no_fifo_space = 1;
01244                         break;
01245                 }
01246 
01247                 
01248 
01249 
01250 
01251 
01252 
01253 
01254                 if (hcd->core_if->dma_enable || status == 0 ||
01255                     qh->channel->requests == qh->channel->multi_count) {
01256                         qh_ptr = qh_ptr->next;
01257                         
01258 
01259 
01260 
01261                         DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
01262                                            &qh->qh_list_entry);
01263 
01264                         
01265                         hcd->core_if->queuing_high_bandwidth = 0;
01266                 }
01267         }
01268 
01269         if (!hcd->core_if->dma_enable) {
01270                 dwc_otg_core_global_regs_t *global_regs;
01271                 gintmsk_data_t intr_mask = {.d32 = 0 };
01272 
01273                 global_regs = hcd->core_if->core_global_regs;
01274                 intr_mask.b.ptxfempty = 1;
01275 #ifdef DEBUG
01276                 tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts);
01277                 DWC_DEBUGPL(DBG_HCDV,
01278                             "  P Tx Req Queue Space Avail (after queue): %d\n",
01279                             tx_status.b.ptxqspcavail);
01280                 DWC_DEBUGPL(DBG_HCDV,
01281                             "  P Tx FIFO Space Avail (after queue): %d\n",
01282                             tx_status.b.ptxfspcavail);
01283 #endif
01284                 if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
01285                     no_queue_space || no_fifo_space) {
01286                         
01287 
01288 
01289 
01290 
01291 
01292 
01293                         dwc_modify_reg32(&global_regs->gintmsk, 0,
01294                                          intr_mask.d32);
01295                 } else {
01296                         
01297 
01298 
01299 
01300 
01301 
01302 
01303                         dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32,
01304                                          0);
01305                 }
01306         }
01307 }
01308 
01316 static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
01317 {
01318         gnptxsts_data_t tx_status;
01319         dwc_list_link_t *orig_qh_ptr;
01320         dwc_otg_qh_t *qh;
01321         int status;
01322         int no_queue_space = 0;
01323         int no_fifo_space = 0;
01324         int more_to_do = 0;
01325 
01326         dwc_otg_core_global_regs_t *global_regs =
01327             hcd->core_if->core_global_regs;
01328 
01329         DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
01330 #ifdef DEBUG
01331         tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts);
01332         DWC_DEBUGPL(DBG_HCDV,
01333                     "  NP Tx Req Queue Space Avail (before queue): %d\n",
01334                     tx_status.b.nptxqspcavail);
01335         DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
01336                     tx_status.b.nptxfspcavail);
01337 #endif
01338         
01339 
01340 
01341 
01342         if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
01343                 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
01344         }
01345         orig_qh_ptr = hcd->non_periodic_qh_ptr;
01346 
01347         
01348 
01349 
01350 
01351         do {
01352                 tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts);
01353                 if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
01354                         no_queue_space = 1;
01355                         break;
01356                 }
01357 
01358                 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
01359                                     qh_list_entry);
01360                 status =
01361                     queue_transaction(hcd, qh->channel,
01362                                       tx_status.b.nptxfspcavail);
01363 
01364                 if (status > 0) {
01365                         more_to_do = 1;
01366                 } else if (status < 0) {
01367                         no_fifo_space = 1;
01368                         break;
01369                 }
01370 
01371                 
01372                 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
01373                 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
01374                         hcd->non_periodic_qh_ptr =
01375                             hcd->non_periodic_qh_ptr->next;
01376                 }
01377 
01378         } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
01379 
01380         if (!hcd->core_if->dma_enable) {
01381                 gintmsk_data_t intr_mask = {.d32 = 0 };
01382                 intr_mask.b.nptxfempty = 1;
01383 
01384 #ifdef DEBUG
01385                 tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts);
01386                 DWC_DEBUGPL(DBG_HCDV,
01387                             "  NP Tx Req Queue Space Avail (after queue): %d\n",
01388                             tx_status.b.nptxqspcavail);
01389                 DWC_DEBUGPL(DBG_HCDV,
01390                             "  NP Tx FIFO Space Avail (after queue): %d\n",
01391                             tx_status.b.nptxfspcavail);
01392 #endif
01393                 if (more_to_do || no_queue_space || no_fifo_space) {
01394                         
01395 
01396 
01397 
01398 
01399 
01400 
01401                         dwc_modify_reg32(&global_regs->gintmsk, 0,
01402                                          intr_mask.d32);
01403                 } else {
01404                         
01405 
01406 
01407 
01408 
01409 
01410 
01411                         dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32,
01412                                          0);
01413                 }
01414         }
01415 }
01416 
01426 void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
01427                                            dwc_otg_transaction_type_e tr_type)
01428 {
01429 #ifdef DEBUG_SOF
01430         DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
01431 #endif
01432         
01433         if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
01434              tr_type == DWC_OTG_TRANSACTION_ALL) &&
01435             !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
01436 
01437                 process_periodic_channels(hcd);
01438         }
01439 
01440         
01441         if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
01442             tr_type == DWC_OTG_TRANSACTION_ALL) {
01443                 if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
01444                         process_non_periodic_channels(hcd);
01445                 } else {
01446                         
01447 
01448 
01449 
01450                         gintmsk_data_t gintmsk = {.d32 = 0 };
01451                         gintmsk.b.nptxfempty = 1;
01452                         dwc_modify_reg32(&hcd->core_if->core_global_regs->
01453                                          gintmsk, gintmsk.d32, 0);
01454                 }
01455         }
01456 }
01457  
01458 #ifdef DWC_HS_ELECT_TST
01459 
01460 
01461 
01462 
01463 
01464 
01465 
01466 
01467 
01468 
01469 
01470 
01471 
01472 static dwc_otg_core_global_regs_t *global_regs;
01473 static dwc_otg_host_global_regs_t *hc_global_regs;
01474 static dwc_otg_hc_regs_t *hc_regs;
01475 static uint32_t *data_fifo;
01476 
01477 static void do_setup(void)
01478 {
01479         gintsts_data_t gintsts;
01480         hctsiz_data_t hctsiz;
01481         hcchar_data_t hcchar;
01482         haint_data_t haint;
01483         hcint_data_t hcint;
01484 
01485         
01486         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);
01487 
01488         
01489         dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);
01490 
01491         
01492         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01493 
01494         
01495         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01496 
01497         
01498         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01499 
01500         
01501         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01502 
01503         
01504         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01505 
01506         
01507         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01508 
01509         
01510         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01511 
01512         
01513         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01514 
01515         
01516 
01517 
01518 
01519         
01520         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01521         if (hcchar.b.chen) {
01522                 hcchar.b.chdis = 1;
01523 
01524                 dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01525                 
01526                 dwc_mdelay(1000);
01527 
01528                 
01529                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01530 
01531                 
01532                 haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01533 
01534                 
01535                 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01536 
01537                 
01538                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01539 
01540                 
01541                 dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01542 
01543                 
01544                 dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01545 
01546                 
01547                 dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01548 
01549                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01550         }
01551 
01552         
01553         hctsiz.d32 = 0;
01554         hctsiz.b.xfersize = 8;
01555         hctsiz.b.pktcnt = 1;
01556         hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
01557         dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
01558 
01559         
01560         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01561         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
01562         hcchar.b.epdir = 0;
01563         hcchar.b.epnum = 0;
01564         hcchar.b.mps = 8;
01565         hcchar.b.chen = 1;
01566         dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01567 
01568         
01569         data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
01570         dwc_write_reg32(data_fifo++, 0x01000680);
01571         dwc_write_reg32(data_fifo++, 0x00080000);
01572 
01573         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01574 
01575         
01576         do {
01577                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01578         } while (gintsts.b.hcintr == 0);
01579 
01580 
01581         
01582         dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);
01583 
01584         
01585         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);
01586 
01587         
01588         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01589 
01590         
01591         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01592 
01593         
01594         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01595 
01596         
01597         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01598 
01599         
01600         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01601 
01602         
01603         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01604 
01605         
01606         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01607 }
01608 
01609 static void do_in_ack(void)
01610 {
01611         gintsts_data_t gintsts;
01612         hctsiz_data_t hctsiz;
01613         hcchar_data_t hcchar;
01614         haint_data_t haint;
01615         hcint_data_t hcint;
01616         host_grxsts_data_t grxsts;
01617 
01618         
01619         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);
01620 
01621         
01622         dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);
01623 
01624         
01625         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01626 
01627         
01628         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01629 
01630         
01631         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01632 
01633         
01634         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01635 
01636         
01637         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01638 
01639         
01640         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01641 
01642         
01643         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01644 
01645         
01646         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01647 
01648         
01649 
01650 
01651 
01652         
01653         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01654         if (hcchar.b.chen) {
01655                 hcchar.b.chdis = 1;
01656                 hcchar.b.chen = 1;
01657                 dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01658                 
01659                 dwc_mdelay(1000);
01660 
01661                 
01662                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01663 
01664                 
01665                 haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01666 
01667                 
01668                 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01669 
01670                 
01671                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01672 
01673                 
01674                 dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01675 
01676                 
01677                 dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01678 
01679                 
01680                 dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01681 
01682                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01683         }
01684 
01685         
01686         hctsiz.d32 = 0;
01687         hctsiz.b.xfersize = 8;
01688         hctsiz.b.pktcnt = 1;
01689         hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
01690         dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
01691 
01692         
01693         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01694         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
01695         hcchar.b.epdir = 1;
01696         hcchar.b.epnum = 0;
01697         hcchar.b.mps = 8;
01698         hcchar.b.chen = 1;
01699         dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01700 
01701         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01702 
01703         
01704         do {
01705                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01706         } while (gintsts.b.rxstsqlvl == 0);
01707 
01708 
01709         
01710         grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp);
01711 
01712         
01713         gintsts.d32 = 0;
01714         gintsts.b.rxstsqlvl = 1;
01715         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01716 
01717         switch (grxsts.b.pktsts) {
01718         case DWC_GRXSTS_PKTSTS_IN:
01719                 
01720                 if (grxsts.b.bcnt > 0) {
01721                         int i;
01722                         int word_count = (grxsts.b.bcnt + 3) / 4;
01723 
01724                         data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
01725 
01726                         for (i = 0; i < word_count; i++) {
01727                                 (void)dwc_read_reg32(data_fifo++);
01728                         }
01729                 }
01730                 break;
01731 
01732         default:
01733                 break;
01734         }
01735 
01736         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01737 
01738         
01739         do {
01740                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01741         } while (gintsts.b.rxstsqlvl == 0);
01742 
01743 
01744         
01745         grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp);
01746 
01747         
01748         gintsts.d32 = 0;
01749         gintsts.b.rxstsqlvl = 1;
01750         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01751 
01752         switch (grxsts.b.pktsts) {
01753         case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
01754                 break;
01755 
01756         default:
01757                 break;
01758         }
01759 
01760         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01761 
01762         
01763         do {
01764                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01765         } while (gintsts.b.hcintr == 0);
01766 
01767 
01768         
01769         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01770 
01771         
01772         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01773 
01774         
01775         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01776 
01777         
01778         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01779 
01780         
01781         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01782 
01783         
01784         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01785 
01786         
01787         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01788 
01789 
01790 
01791         dwc_mdelay(1);
01792 
01793         
01794 
01795 
01796 
01797         
01798         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01799 
01800         
01801         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01802 
01803         
01804         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01805 
01806         
01807         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01808 
01809         
01810         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01811 
01812         
01813         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01814 
01815         
01816         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01817 
01818         
01819         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01820         if (hcchar.b.chen) {
01821                 hcchar.b.chdis = 1;
01822                 hcchar.b.chen = 1;
01823                 dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01824                 
01825                 dwc_mdelay(1000);
01826 
01827                 
01828                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01829 
01830                 
01831                 haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01832 
01833                 
01834                 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01835 
01836                 
01837                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01838 
01839                 
01840                 dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01841 
01842                 
01843                 dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01844 
01845                 
01846                 dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01847 
01848                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01849         }
01850 
01851         
01852         hctsiz.d32 = 0;
01853         hctsiz.b.xfersize = 0;
01854         hctsiz.b.pktcnt = 1;
01855         hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
01856         dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
01857 
01858         
01859         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01860         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
01861         hcchar.b.epdir = 0;
01862         hcchar.b.epnum = 0;
01863         hcchar.b.mps = 8;
01864         hcchar.b.chen = 1;
01865         dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01866 
01867         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01868 
01869         
01870         do {
01871                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01872         } while (gintsts.b.hcintr == 0);
01873 
01874 
01875         
01876         dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);
01877 
01878         
01879         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);
01880 
01881         
01882         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01883 
01884         
01885         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01886 
01887         
01888         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01889 
01890         
01891         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01892 
01893         
01894         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01895 
01896         
01897         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01898 
01899         
01900         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01901 }
01902 #endif
01903 
01905 int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
01906                             uint16_t typeReq,
01907                             uint16_t wValue,
01908                             uint16_t wIndex, uint8_t * buf, uint16_t wLength)
01909 {
01910         int retval = 0;
01911 
01912         dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
01913         usb_hub_descriptor_t *hub_desc;
01914         hprt0_data_t hprt0 = {.d32 = 0 };
01915 
01916         uint32_t port_status;
01917 
01918         switch (typeReq) {
01919         case UCR_CLEAR_HUB_FEATURE:
01920                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
01921                             "ClearHubFeature 0x%x\n", wValue);
01922                 switch (wValue) {
01923                 case UHF_C_HUB_LOCAL_POWER:
01924                 case UHF_C_HUB_OVER_CURRENT:
01925                         
01926                         break;
01927                 default:
01928                         retval = -DWC_E_INVALID;
01929                         DWC_ERROR("DWC OTG HCD - "
01930                                   "ClearHubFeature request %xh unknown\n",
01931                                   wValue);
01932                 }
01933                 break;
01934         case UCR_CLEAR_PORT_FEATURE:
01935 #ifdef CONFIG_USB_DWC_OTG_LPM
01936                 if (wValue != UHF_PORT_L1)
01937 #endif
01938                         if (!wIndex || wIndex > 1)
01939                                 goto error;
01940 
01941                 switch (wValue) {
01942                 case UHF_PORT_ENABLE:
01943                         DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
01944                                     "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
01945                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
01946                         hprt0.b.prtena = 1;
01947                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
01948                         break;
01949                 case UHF_PORT_SUSPEND:
01950                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
01951                                     "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
01952 
01953                         dwc_write_reg32(core_if->pcgcctl, 0);
01954                         dwc_mdelay(5);
01955 
01956                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
01957                         hprt0.b.prtres = 1;
01958                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
01959                         hprt0.b.prtsusp = 0;
01960                         
01961                         dwc_mdelay(100);
01962                         hprt0.b.prtres = 0;
01963                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
01964                         break;
01965 #ifdef CONFIG_USB_DWC_OTG_LPM
01966                 case UHF_PORT_L1:
01967                         {
01968                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
01969                                 glpmcfg_data_t lpmcfg = {.d32 = 0 };
01970 
01971                                 lpmcfg.d32 =
01972                                     dwc_read_reg32(&core_if->core_global_regs->
01973                                                    glpmcfg);
01974                                 lpmcfg.b.en_utmi_sleep = 0;
01975                                 lpmcfg.b.hird_thres &= (~(1 << 4));
01976                                 lpmcfg.b.prt_sleep_sts = 1;
01977                                 dwc_write_reg32(&core_if->core_global_regs->
01978                                                 glpmcfg, lpmcfg.d32);
01979 
01980                                 
01981                                 pcgcctl.b.enbl_sleep_gating = 1;
01982                                 dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32,
01983                                                  0);
01984 
01985                                 dwc_mdelay(5);
01986 
01987                                 hprt0.d32 = dwc_otg_read_hprt0(core_if);
01988                                 hprt0.b.prtres = 1;
01989                                 dwc_write_reg32(core_if->host_if->hprt0,
01990                                                 hprt0.d32);
01991                                 
01992                                 break;
01993                         }
01994 #endif
01995                 case UHF_PORT_POWER:
01996                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
01997                                     "ClearPortFeature USB_PORT_FEAT_POWER\n");
01998                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
01999                         hprt0.b.prtpwr = 0;
02000                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
02001                         break;
02002                 case UHF_PORT_INDICATOR:
02003                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02004                                     "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
02005                         
02006                         break;
02007                 case UHF_C_PORT_CONNECTION:
02008                         
02009 
02010                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02011                                     "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
02012                         dwc_otg_hcd->flags.b.port_connect_status_change = 0;
02013                         break;
02014                 case UHF_C_PORT_RESET:
02015                         
02016 
02017                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02018                                     "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
02019                         dwc_otg_hcd->flags.b.port_reset_change = 0;
02020                         break;
02021                 case UHF_C_PORT_ENABLE:
02022                         
02023 
02024                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02025                                     "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
02026                         dwc_otg_hcd->flags.b.port_enable_change = 0;
02027                         break;
02028                 case UHF_C_PORT_SUSPEND:
02029                         
02030 
02031 
02032                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02033                                     "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
02034                         dwc_otg_hcd->flags.b.port_suspend_change = 0;
02035                         break;
02036 #ifdef CONFIG_USB_DWC_OTG_LPM
02037                 case UHF_C_PORT_L1:
02038                         dwc_otg_hcd->flags.b.port_l1_change = 0;
02039                         break;
02040 #endif
02041                 case UHF_C_PORT_OVER_CURRENT:
02042                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02043                                     "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
02044                         dwc_otg_hcd->flags.b.port_over_current_change = 0;
02045                         break;
02046                 default:
02047                         retval = -DWC_E_INVALID;
02048                         DWC_ERROR("DWC OTG HCD - "
02049                                   "ClearPortFeature request %xh "
02050                                   "unknown or unsupported\n", wValue);
02051                 }
02052                 break;
02053         case UCR_GET_HUB_DESCRIPTOR:
02054                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02055                             "GetHubDescriptor\n");
02056                 hub_desc = (usb_hub_descriptor_t *) buf;
02057                 hub_desc->bDescLength = 9;
02058                 hub_desc->bDescriptorType = 0x29;
02059                 hub_desc->bNbrPorts = 1;
02060                 USETW(hub_desc->wHubCharacteristics, 0x08);
02061                 hub_desc->bPwrOn2PwrGood = 1;
02062                 hub_desc->bHubContrCurrent = 0;
02063                 hub_desc->DeviceRemovable[0] = 0;
02064                 hub_desc->DeviceRemovable[1] = 0xff;
02065                 break;
02066         case UCR_GET_HUB_STATUS:
02067                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02068                             "GetHubStatus\n");
02069                 DWC_MEMSET(buf, 0, 4);
02070                 break;
02071         case UCR_GET_PORT_STATUS:
02072                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02073                             "GetPortStatus\n");
02074                 if (!wIndex || wIndex > 1)
02075                         goto error;
02076 
02077                 port_status = 0;
02078 
02079                 if (dwc_otg_hcd->flags.b.port_connect_status_change)
02080                         port_status |= (1 << UHF_C_PORT_CONNECTION);
02081 
02082                 if (dwc_otg_hcd->flags.b.port_enable_change)
02083                         port_status |= (1 << UHF_C_PORT_ENABLE);
02084 
02085                 if (dwc_otg_hcd->flags.b.port_suspend_change)
02086                         port_status |= (1 << UHF_C_PORT_SUSPEND);
02087 
02088                 if (dwc_otg_hcd->flags.b.port_l1_change)
02089                         port_status |= (1 << UHF_C_PORT_L1);
02090 
02091                 if (dwc_otg_hcd->flags.b.port_reset_change) {
02092                         port_status |= (1 << UHF_C_PORT_RESET);
02093                 }
02094 
02095                 if (dwc_otg_hcd->flags.b.port_over_current_change) {
02096                         DWC_ERROR("Device Not Supported\n");
02097                         port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
02098                 }
02099 
02100                 if (!dwc_otg_hcd->flags.b.port_connect_status) {
02101                         
02102 
02103 
02104 
02105 
02106 
02107 
02108                         *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
02109                         break;
02110                 }
02111 
02112                 hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
02113                 DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
02114 
02115                 if (hprt0.b.prtconnsts)
02116                         port_status |= (1 << UHF_PORT_CONNECTION);
02117 
02118                 if (hprt0.b.prtena)
02119                         port_status |= (1 << UHF_PORT_ENABLE);
02120 
02121                 if (hprt0.b.prtsusp)
02122                         port_status |= (1 << UHF_PORT_SUSPEND);
02123 
02124                 if (hprt0.b.prtovrcurract)
02125                         port_status |= (1 << UHF_PORT_OVER_CURRENT);
02126 
02127                 if (hprt0.b.prtrst)
02128                         port_status |= (1 << UHF_PORT_RESET);
02129 
02130                 if (hprt0.b.prtpwr)
02131                         port_status |= (1 << UHF_PORT_POWER);
02132 
02133                 if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
02134                         port_status |= (1 << UHF_PORT_HIGH_SPEED);
02135                 else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
02136                         port_status |= (1 << UHF_PORT_LOW_SPEED);
02137 
02138                 if (hprt0.b.prttstctl)
02139                         port_status |= (1 << UHF_PORT_TEST);
02140                 if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
02141                         port_status |= (1 << UHF_PORT_L1);
02142                 }
02143 
02144                 
02145 
02146                 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
02147 
02148                 break;
02149         case UCR_SET_HUB_FEATURE:
02150                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02151                             "SetHubFeature\n");
02152                 
02153                 break;
02154         case UCR_SET_PORT_FEATURE:
02155                 if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
02156                         goto error;
02157 
02158                 if (!dwc_otg_hcd->flags.b.port_connect_status) {
02159                         
02160 
02161 
02162 
02163 
02164 
02165 
02166                         break;
02167                 }
02168 
02169                 switch (wValue) {
02170                 case UHF_PORT_SUSPEND:
02171                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02172                                     "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
02173                         if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
02174                             dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
02175                                 gotgctl_data_t gotgctl = {.d32 = 0 };
02176                                 gotgctl.b.hstsethnpen = 1;
02177                                 dwc_modify_reg32(&core_if->core_global_regs->
02178                                                  gotgctl, 0, gotgctl.d32);
02179                                 core_if->op_state = A_SUSPEND;
02180                         }
02181                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
02182                         hprt0.b.prtsusp = 1;
02183                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
02184                         {
02185                                 uint64_t flags;
02186                                 
02187                                 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
02188                                 core_if->lx_state = DWC_OTG_L2;
02189                                 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
02190                         }
02191                         
02192                         {
02193                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
02194                                 pcgcctl.b.stoppclk = 1;
02195                                 dwc_modify_reg32(core_if->pcgcctl, 0,
02196                                                  pcgcctl.d32);
02197                         }
02198 
02199                         
02200                         if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
02201                                 dwc_mdelay(200);
02202                         }
02203                         break;
02204                 case UHF_PORT_POWER:
02205                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02206                                     "SetPortFeature - USB_PORT_FEAT_POWER\n");
02207                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
02208                         hprt0.b.prtpwr = 1;
02209                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
02210                         break;
02211                 case UHF_PORT_RESET:
02212                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02213                                     "SetPortFeature - USB_PORT_FEAT_RESET\n");
02214                         {
02215                                 pcgcctl_data_t pcgcctl = {.d32 = 0 };
02216                                 pcgcctl.b.enbl_sleep_gating = 1;
02217                                 pcgcctl.b.stoppclk = 1;
02218                                 dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32,
02219                                                  0);
02220                                 dwc_write_reg32(core_if->pcgcctl, 0);
02221                         }
02222 #ifdef CONFIG_USB_DWC_OTG_LPM
02223                         {
02224                                 glpmcfg_data_t lpmcfg;
02225                                 lpmcfg.d32 =
02226                                     dwc_read_reg32(&core_if->core_global_regs->
02227                                                    glpmcfg);
02228                                 if (lpmcfg.b.prt_sleep_sts) {
02229                                         lpmcfg.b.en_utmi_sleep = 0;
02230                                         lpmcfg.b.hird_thres &= (~(1 << 4));
02231                                         dwc_write_reg32(&core_if->
02232                                                         core_global_regs->
02233                                                         glpmcfg, lpmcfg.d32);
02234                                         dwc_mdelay(1);
02235                                 }
02236                         }
02237 #endif
02238                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
02239                         
02240 
02241 
02242 
02243                         if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
02244                                 hprt0.b.prtrst = 1;
02245                                 dwc_write_reg32(core_if->host_if->hprt0,
02246                                                 hprt0.d32);
02247                         }
02248                         
02249                         dwc_mdelay(60);
02250                         hprt0.b.prtrst = 0;
02251                         dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
02252                         core_if->lx_state = DWC_OTG_L0; 
02253                         break;
02254 #ifdef DWC_HS_ELECT_TST
02255                 case UHF_PORT_TEST:
02256                         {
02257                                 uint32_t t;
02258                                 gintmsk_data_t gintmsk;
02259 
02260                                 t = (wIndex >> 8);      
02261                                 DWC_DEBUGPL(DBG_HCD,
02262                                             "DWC OTG HCD HUB CONTROL - "
02263                                             "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
02264                                             t);
02265                                 DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
02266                                 if (t < 6) {
02267                                         hprt0.d32 = dwc_otg_read_hprt0(core_if);
02268                                         hprt0.b.prttstctl = t;
02269                                         dwc_write_reg32(core_if->host_if->hprt0,
02270                                                         hprt0.d32);
02271                                 } else {
02272                                         
02273 
02274 
02275                                         global_regs = core_if->core_global_regs;
02276                                         hc_global_regs =
02277                                             core_if->host_if->host_global_regs;
02278                                         hc_regs =
02279                                             (dwc_otg_hc_regs_t *) ((char *)
02280                                                                    global_regs +
02281                                                                    0x500);
02282                                         data_fifo =
02283                                             (uint32_t *) ((char *)global_regs +
02284                                                           0x1000);
02285 
02286                                         if (t == 6) {   
02287                                                 
02288                                                 gintmsk.d32 =
02289                                                     dwc_read_reg32
02290                                                     (&global_regs->gintmsk);
02291 
02292                                                 
02293 
02294 
02295                                                 dwc_write_reg32(&global_regs->
02296                                                                 gintmsk, 0);
02297 
02298                                                 
02299                                                 dwc_mdelay(15000);
02300 
02301                                                 
02302                                                 hprt0.d32 =
02303                                                     dwc_otg_read_hprt0(core_if);
02304                                                 hprt0.b.prtsusp = 1;
02305                                                 hprt0.b.prtres = 0;
02306                                                 dwc_write_reg32(core_if->
02307                                                                 host_if->hprt0,
02308                                                                 hprt0.d32);
02309 
02310                                                 
02311                                                 dwc_mdelay(15000);
02312 
02313                                                 
02314                                                 hprt0.d32 =
02315                                                     dwc_otg_read_hprt0(core_if);
02316                                                 hprt0.b.prtsusp = 0;
02317                                                 hprt0.b.prtres = 1;
02318                                                 dwc_write_reg32(core_if->
02319                                                                 host_if->hprt0,
02320                                                                 hprt0.d32);
02321                                                 dwc_mdelay(100);
02322 
02323                                                 
02324                                                 hprt0.b.prtres = 0;
02325                                                 dwc_write_reg32(core_if->
02326                                                                 host_if->hprt0,
02327                                                                 hprt0.d32);
02328 
02329                                                 
02330                                                 dwc_write_reg32(&global_regs->
02331                                                                 gintmsk,
02332                                                                 gintmsk.d32);
02333                                         } else if (t == 7) {    
02334                                                 
02335                                                 gintmsk.d32 =
02336                                                     dwc_read_reg32
02337                                                     (&global_regs->gintmsk);
02338 
02339                                                 
02340 
02341 
02342                                                 dwc_write_reg32(&global_regs->
02343                                                                 gintmsk, 0);
02344 
02345                                                 
02346                                                 dwc_mdelay(15000);
02347 
02348                                                 
02349                                                 do_setup();
02350 
02351                                                 
02352                                                 dwc_mdelay(15000);
02353 
02354                                                 
02355                                                 dwc_write_reg32(&global_regs->
02356                                                                 gintmsk,
02357                                                                 gintmsk.d32);
02358                                         } else if (t == 8) {    
02359                                                 
02360                                                 gintmsk.d32 =
02361                                                     dwc_read_reg32
02362                                                     (&global_regs->gintmsk);
02363 
02364                                                 
02365 
02366 
02367                                                 dwc_write_reg32(&global_regs->
02368                                                                 gintmsk, 0);
02369 
02370                                                 
02371                                                 do_setup();
02372 
02373                                                 
02374                                                 dwc_mdelay(15000);
02375 
02376                                                 
02377                                                 do_in_ack();
02378 
02379                                                 
02380                                                 dwc_mdelay(15000);
02381 
02382                                                 
02383                                                 dwc_write_reg32(&global_regs->
02384                                                                 gintmsk,
02385                                                                 gintmsk.d32);
02386                                         }
02387                                 }
02388                                 break;
02389                         }
02390 #endif                          
02391 
02392                 case UHF_PORT_INDICATOR:
02393                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02394                                     "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
02395                         
02396                         break;
02397                 default:
02398                         retval = -DWC_E_INVALID;
02399                         DWC_ERROR("DWC OTG HCD - "
02400                                   "SetPortFeature request %xh "
02401                                   "unknown or unsupported\n", wValue);
02402                         break;
02403                 }
02404                 break;
02405 #ifdef CONFIG_USB_DWC_OTG_LPM
02406         case UCR_SET_AND_TEST_PORT_FEATURE:
02407                 if (wValue != UHF_PORT_L1) {
02408                         goto error;
02409                 }
02410                 {
02411                         int portnum, hird, devaddr, remwake;
02412                         glpmcfg_data_t lpmcfg;
02413                         uint32_t time_usecs;
02414                         gintsts_data_t gintsts;
02415                         gintmsk_data_t gintmsk;
02416 
02417                         if (!dwc_otg_get_param_lpm_enable(core_if)) {
02418                                 goto error;
02419                         }
02420                         if (wValue != UHF_PORT_L1 || wLength != 1) {
02421                                 goto error;
02422                         }
02423                         
02424                         lpmcfg.d32 =
02425                             dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
02426                         if (lpmcfg.b.prt_sleep_sts) {
02427                                 DWC_INFO("Port is already in sleep mode\n");
02428                                 buf[0] = 0;     
02429                                 break;
02430                         }
02431 
02432                         portnum = wIndex & 0xf;
02433                         hird = (wIndex >> 4) & 0xf;
02434                         devaddr = (wIndex >> 8) & 0x7f;
02435                         remwake = (wIndex >> 15);
02436 
02437                         if (portnum != 1) {
02438                                 retval = -DWC_E_INVALID;
02439                                 DWC_WARN
02440                                     ("Wrong port number(%d) in SetandTestPortFeature request\n",
02441                                      portnum);
02442                                 break;
02443                         }
02444 
02445                         DWC_PRINTF
02446                             ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
02447                              portnum, hird, devaddr, remwake);
02448                         
02449                         gintmsk.d32 = 0;
02450                         gintmsk.b.lpmtranrcvd = 1;
02451                         dwc_modify_reg32(&core_if->core_global_regs->gintmsk,
02452                                          gintmsk.d32, 0);
02453 
02454                         if (dwc_otg_hcd_send_lpm
02455                             (dwc_otg_hcd, devaddr, hird, remwake)) {
02456                                 retval = -DWC_E_INVALID;
02457                                 break;
02458                         }
02459 
02460                         time_usecs = 10 * (lpmcfg.b.retry_count + 1);
02461                         
02462 
02463 
02464 
02465 
02466                         do {
02467                                 gintsts.d32 =
02468                                     dwc_read_reg32(&core_if->core_global_regs->
02469                                                    gintsts);
02470                                 if (gintsts.b.lpmtranrcvd) {
02471                                         break;
02472                                 }
02473                                 dwc_udelay(1);
02474                         } while (--time_usecs);
02475                         
02476 
02477                         
02478 
02479 
02480 
02481 
02482                         if (!gintsts.b.lpmtranrcvd) {
02483                                 buf[0] = 0x3;   
02484                                 dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
02485                         } else {
02486                                 lpmcfg.d32 =
02487                                     dwc_read_reg32(&core_if->core_global_regs->
02488                                                    glpmcfg);
02489                                 if (lpmcfg.b.lpm_resp == 0x3) {
02490                                         
02491                                         buf[0] = 0x00;  
02492                                 } else if (lpmcfg.b.lpm_resp == 0x2) {
02493                                         
02494                                         buf[0] = 0x2;
02495                                 } else {
02496                                         
02497                                         buf[0] = 0x3;
02498                                 }
02499                         }
02500                         DWC_PRINTF("Device responce to LPM trans is %x\n",
02501                                    lpmcfg.b.lpm_resp);
02502                         dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0,
02503                                          gintmsk.d32);
02504 
02505                         break;
02506                 }
02507 #endif                          
02508         default:
02509               error:
02510                 retval = -DWC_E_INVALID;
02511                 DWC_WARN("DWC OTG HCD - "
02512                          "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
02513                          typeReq, wIndex, wValue);
02514                 break;
02515         }
02516 
02517         return retval;
02518 }
02519 
02520 #ifdef CONFIG_USB_DWC_OTG_LPM
02521 
02522 int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
02523 {
02524         dwc_otg_core_if_t *core_if = hcd->core_if;
02525         dwc_hc_t *hc;
02526         hcchar_data_t hcchar;
02527         gintmsk_data_t gintmsk = {.d32 = 0 };
02528 
02529         if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
02530                 DWC_PRINTF("No free channel to select for LPM transaction\n");
02531                 return -1;
02532         }
02533 
02534         hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
02535 
02536         
02537         gintmsk.b.hcintr = 1;
02538         dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
02539 
02540         
02541         hcchar.b.devaddr = devaddr;
02542         hcchar.b.epnum = 0;
02543         hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
02544         hcchar.b.mps = 64;
02545         hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
02546         hcchar.b.epdir = 0;     
02547         dwc_write_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
02548                         hcchar.d32);
02549 
02550         
02551         DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
02552 
02553         DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
02554 
02555         return hc->hc_num;
02556 }
02557 
02559 void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
02560 {
02561         dwc_hc_t *hc;
02562         glpmcfg_data_t lpmcfg;
02563         uint8_t hc_num;
02564 
02565         lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg);
02566         hc_num = lpmcfg.b.lpm_chan_index;
02567 
02568         hc = hcd->hc_ptr_array[hc_num];
02569 
02570         DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
02571         
02572         DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
02573 }
02574 
02575 int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
02576                          uint8_t bRemoteWake)
02577 {
02578         glpmcfg_data_t lpmcfg;
02579         pcgcctl_data_t pcgcctl = {.d32 = 0 };
02580         int channel;
02581 
02582         channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
02583         if (channel < 0) {
02584                 return channel;
02585         }
02586 
02587         pcgcctl.b.enbl_sleep_gating = 1;
02588         dwc_modify_reg32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
02589 
02590         
02591         lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg);
02592 
02593         
02594         lpmcfg.b.rem_wkup_en = bRemoteWake;
02595         lpmcfg.b.hird = hird;
02596         lpmcfg.b.hird_thres = 0x1c;
02597         lpmcfg.b.lpm_chan_index = channel;
02598         lpmcfg.b.en_utmi_sleep = 1;
02599         
02600         dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
02601 
02602         
02603         lpmcfg.b.send_lpm = 1;
02604         dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
02605 
02606         return 0;
02607 }
02608 
02609 #endif                          
02610 
02611 int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
02612 {
02613         int retval;
02614 
02615         if (port != 1) {
02616                 return -DWC_E_INVALID;
02617         }
02618 
02619         retval = (hcd->flags.b.port_connect_status_change ||
02620                   hcd->flags.b.port_reset_change ||
02621                   hcd->flags.b.port_enable_change ||
02622                   hcd->flags.b.port_suspend_change ||
02623                   hcd->flags.b.port_over_current_change);
02624 #ifdef DEBUG
02625         if (retval) {
02626                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
02627                             " Root port status changed\n");
02628                 DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
02629                             hcd->flags.b.port_connect_status_change);
02630                 DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
02631                             hcd->flags.b.port_reset_change);
02632                 DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
02633                             hcd->flags.b.port_enable_change);
02634                 DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
02635                             hcd->flags.b.port_suspend_change);
02636                 DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
02637                             hcd->flags.b.port_over_current_change);
02638         }
02639 #endif
02640         return retval;
02641 }
02642 
02643 int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
02644 {
02645         hfnum_data_t hfnum;
02646         hfnum.d32 = dwc_read_reg32(&dwc_otg_hcd->core_if->
02647                                    host_if->host_global_regs->hfnum);
02648 
02649 #ifdef DEBUG_SOF
02650         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
02651                     hfnum.b.frnum);
02652 #endif
02653         return hfnum.b.frnum;
02654 }
02655 
02656 int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
02657                       struct dwc_otg_hcd_function_ops *fops)
02658 {
02659         int retval = 0;
02660 
02661         hcd->fops = fops;
02662         if (!dwc_otg_is_device_mode(hcd->core_if)) {
02663                 dwc_otg_hcd_reinit(hcd);
02664         } else {
02665                 retval = -DWC_E_NO_DEVICE;
02666         }
02667 
02668         return retval;
02669 }
02670 
02671 void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
02672 {
02673         return hcd->priv;
02674 }
02675 
02676 void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
02677 {
02678         hcd->priv = priv_data;
02679 }
02680 
02681 uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
02682 {
02683         return hcd->otg_port;
02684 }
02685 
02686 uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
02687 {
02688         uint32_t is_b_host;
02689         if (hcd->core_if->op_state == B_HOST) {
02690                 is_b_host = 1;
02691         } else {
02692                 is_b_host = 0;
02693         }
02694 
02695         return is_b_host;
02696 }
02697 
02698 dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
02699                                          int iso_desc_count, int atomic_alloc)
02700 {
02701         dwc_otg_hcd_urb_t *dwc_otg_urb;
02702         uint32_t size;
02703 
02704         size =
02705             sizeof(*dwc_otg_urb) +
02706             iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
02707         if (atomic_alloc) {
02708                 dwc_otg_urb = dwc_alloc_atomic(size);
02709         } else {
02710                 dwc_otg_urb = dwc_alloc(size);
02711         }
02712         dwc_otg_urb->packet_count = iso_desc_count;
02713 
02714         return dwc_otg_urb;
02715 }
02716 
02717 void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
02718                                   uint8_t dev_addr, uint8_t ep_num,
02719                                   uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
02720 {
02721         dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
02722                               ep_type, ep_dir, mps);
02723 #if 0
02724         DWC_PRINTF
02725             ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
02726              dev_addr, ep_num, ep_dir, ep_type, mps);
02727 #endif
02728 }
02729 
02730 void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
02731                                 void *urb_handle, void *buf, dwc_dma_t dma,
02732                                 uint32_t buflen, void *setup_packet,
02733                                 dwc_dma_t setup_dma, uint32_t flags,
02734                                 uint16_t interval)
02735 {
02736         dwc_otg_urb->priv = urb_handle;
02737         dwc_otg_urb->buf = buf;
02738         dwc_otg_urb->dma = dma;
02739         dwc_otg_urb->length = buflen;
02740         dwc_otg_urb->setup_packet = setup_packet;
02741         dwc_otg_urb->setup_dma = setup_dma;
02742         dwc_otg_urb->flags = flags;
02743         dwc_otg_urb->interval = interval;
02744         dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
02745 }
02746 
02747 uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
02748 {
02749         return dwc_otg_urb->status;
02750 }
02751 
02752 uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
02753 {
02754         return dwc_otg_urb->actual_length;
02755 }
02756 
02757 uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
02758 {
02759         return dwc_otg_urb->error_count;
02760 }
02761 
02762 void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
02763                                          int desc_num, uint32_t offset,
02764                                          uint32_t length)
02765 {
02766         dwc_otg_urb->iso_descs[desc_num].offset = offset;
02767         dwc_otg_urb->iso_descs[desc_num].length = length;
02768 }
02769 
02770 uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
02771                                              int desc_num)
02772 {
02773         return dwc_otg_urb->iso_descs[desc_num].status;
02774 }
02775 
02776 uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
02777                                                     dwc_otg_urb, int desc_num)
02778 {
02779         return dwc_otg_urb->iso_descs[desc_num].actual_length;
02780 }
02781 
02782 int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
02783 {
02784         int allocated = 0;
02785         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
02786 
02787         if (qh) {
02788                 if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
02789                         allocated = 1;
02790                 }
02791         }
02792         return allocated;
02793 }
02794 
02795 int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
02796 {
02797         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
02798         int freed = 0;
02799         DWC_ASSERT(qh, "qh is not allocated\n");
02800 
02801         if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
02802                 freed = 1;
02803         }
02804 
02805         return freed;
02806 }
02807 
02808 uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
02809 {
02810         dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
02811         DWC_ASSERT(qh, "qh is not allocated\n");
02812         return qh->usecs;
02813 }
02814 
02815 void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
02816 {
02817 #ifdef DEBUG
02818         int num_channels;
02819         int i;
02820         gnptxsts_data_t np_tx_status;
02821         hptxsts_data_t p_tx_status;
02822 
02823         num_channels = hcd->core_if->core_params->host_channels;
02824         DWC_PRINTF("\n");
02825         DWC_PRINTF
02826             ("************************************************************\n");
02827         DWC_PRINTF("HCD State:\n");
02828         DWC_PRINTF("  Num channels: %d\n", num_channels);
02829         for (i = 0; i < num_channels; i++) {
02830                 dwc_hc_t *hc = hcd->hc_ptr_array[i];
02831                 DWC_PRINTF("  Channel %d:\n", i);
02832                 DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
02833                            hc->dev_addr, hc->ep_num, hc->ep_is_in);
02834                 DWC_PRINTF("    speed: %d\n", hc->speed);
02835                 DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
02836                 DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
02837                 DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
02838                 DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
02839                 DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
02840                 DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
02841                 DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
02842                 DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
02843                 DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
02844                 DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
02845                 DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
02846                 DWC_PRINTF("    do_split: %d\n", hc->do_split);
02847                 DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
02848                 DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
02849                 DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
02850                 DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
02851                 DWC_PRINTF("    requests: %d\n", hc->requests);
02852                 DWC_PRINTF("    qh: %p\n", hc->qh);
02853                 if (hc->xfer_started) {
02854                         hfnum_data_t hfnum;
02855                         hcchar_data_t hcchar;
02856                         hctsiz_data_t hctsiz;
02857                         hcint_data_t hcint;
02858                         hcintmsk_data_t hcintmsk;
02859                         hfnum.d32 =
02860                             dwc_read_reg32(&hcd->core_if->host_if->
02861                                            host_global_regs->hfnum);
02862                         hcchar.d32 =
02863                             dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
02864                                            hcchar);
02865                         hctsiz.d32 =
02866                             dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
02867                                            hctsiz);
02868                         hcint.d32 =
02869                             dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
02870                                            hcint);
02871                         hcintmsk.d32 =
02872                             dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
02873                                            hcintmsk);
02874                         DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
02875                         DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
02876                         DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
02877                         DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
02878                         DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
02879                 }
02880                 if (hc->xfer_started && hc->qh) {
02881                         dwc_otg_qtd_t *qtd;
02882                         dwc_otg_hcd_urb_t *urb;
02883                         
02884                         DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
02885                                 if(!qtd->in_process)
02886                                         break;
02887                                 
02888                                 urb = qtd->urb;
02889                         DWC_PRINTF("    URB Info:\n");
02890                         DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
02891                         if (urb) {
02892                                 DWC_PRINTF("      Dev: %d, EP: %d %s\n",
02893                                            dwc_otg_hcd_get_dev_addr(&urb->
02894                                                                     pipe_info),
02895                                            dwc_otg_hcd_get_ep_num(&urb->
02896                                                                   pipe_info),
02897                                            dwc_otg_hcd_is_pipe_in(&urb->
02898                                                                   pipe_info) ?
02899                                            "IN" : "OUT");
02900                                 DWC_PRINTF("      Max packet size: %d\n",
02901                                            dwc_otg_hcd_get_mps(&urb->
02902                                                                pipe_info));
02903                                 DWC_PRINTF("      transfer_buffer: %p\n",
02904                                            urb->buf);
02905                                 DWC_PRINTF("      transfer_dma: %p\n",
02906                                            (void *)urb->dma);
02907                                 DWC_PRINTF("      transfer_buffer_length: %d\n",
02908                                            urb->length);
02909                                 DWC_PRINTF("      actual_length: %d\n",
02910                                            urb->actual_length);
02911                         }
02912                 }
02913         }
02914         }
02915         DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
02916         DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
02917         DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
02918         np_tx_status.d32 =
02919             dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts);
02920         DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
02921                    np_tx_status.b.nptxqspcavail);
02922         DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
02923                    np_tx_status.b.nptxfspcavail);
02924         p_tx_status.d32 =
02925             dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts);
02926         DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
02927                    p_tx_status.b.ptxqspcavail);
02928         DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
02929         dwc_otg_hcd_dump_frrem(hcd);
02930         dwc_otg_dump_global_registers(hcd->core_if);
02931         dwc_otg_dump_host_registers(hcd->core_if);
02932         DWC_PRINTF
02933             ("************************************************************\n");
02934         DWC_PRINTF("\n");
02935 #endif
02936 }
02937 
02938 #ifdef DEBUG
02939 void dwc_print_setup_data(uint8_t * setup)
02940 {
02941         int i;
02942         if (CHK_DEBUG_LEVEL(DBG_HCD)) {
02943                 DWC_PRINTF("Setup Data = MSB ");
02944                 for (i = 7; i >= 0; i--)
02945                         DWC_PRINTF("%02x ", setup[i]);
02946                 DWC_PRINTF("\n");
02947                 DWC_PRINTF("  bmRequestType Tranfer = %s\n",
02948                            (setup[0] & 0x80) ? "Device-to-Host" :
02949                            "Host-to-Device");
02950                 DWC_PRINTF("  bmRequestType Type = ");
02951                 switch ((setup[0] & 0x60) >> 5) {
02952                 case 0:
02953                         DWC_PRINTF("Standard\n");
02954                         break;
02955                 case 1:
02956                         DWC_PRINTF("Class\n");
02957                         break;
02958                 case 2:
02959                         DWC_PRINTF("Vendor\n");
02960                         break;
02961                 case 3:
02962                         DWC_PRINTF("Reserved\n");
02963                         break;
02964                 }
02965                 DWC_PRINTF("  bmRequestType Recipient = ");
02966                 switch (setup[0] & 0x1f) {
02967                 case 0:
02968                         DWC_PRINTF("Device\n");
02969                         break;
02970                 case 1:
02971                         DWC_PRINTF("Interface\n");
02972                         break;
02973                 case 2:
02974                         DWC_PRINTF("Endpoint\n");
02975                         break;
02976                 case 3:
02977                         DWC_PRINTF("Other\n");
02978                         break;
02979                 default:
02980                         DWC_PRINTF("Reserved\n");
02981                         break;
02982                 }
02983                 DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
02984                 DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
02985                 DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
02986                 DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
02987         }
02988 }
02989 #endif
02990 
02991 void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
02992 {
02993 #if 0
02994         DWC_PRINTF("Frame remaining at SOF:\n");
02995         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
02996                    hcd->frrem_samples, hcd->frrem_accum,
02997                    (hcd->frrem_samples > 0) ?
02998                    hcd->frrem_accum / hcd->frrem_samples : 0);
02999 
03000         DWC_PRINTF("\n");
03001         DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
03002         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03003                    hcd->core_if->hfnum_7_samples,
03004                    hcd->core_if->hfnum_7_frrem_accum,
03005                    (hcd->core_if->hfnum_7_samples >
03006                     0) ? hcd->core_if->hfnum_7_frrem_accum /
03007                    hcd->core_if->hfnum_7_samples : 0);
03008         DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
03009         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03010                    hcd->core_if->hfnum_0_samples,
03011                    hcd->core_if->hfnum_0_frrem_accum,
03012                    (hcd->core_if->hfnum_0_samples >
03013                     0) ? hcd->core_if->hfnum_0_frrem_accum /
03014                    hcd->core_if->hfnum_0_samples : 0);
03015         DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
03016         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03017                    hcd->core_if->hfnum_other_samples,
03018                    hcd->core_if->hfnum_other_frrem_accum,
03019                    (hcd->core_if->hfnum_other_samples >
03020                     0) ? hcd->core_if->hfnum_other_frrem_accum /
03021                    hcd->core_if->hfnum_other_samples : 0);
03022 
03023         DWC_PRINTF("\n");
03024         DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
03025         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03026                    hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
03027                    (hcd->hfnum_7_samples_a > 0) ?
03028                    hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
03029         DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
03030         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03031                    hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
03032                    (hcd->hfnum_0_samples_a > 0) ?
03033                    hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
03034         DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
03035         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03036                    hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
03037                    (hcd->hfnum_other_samples_a > 0) ?
03038                    hcd->hfnum_other_frrem_accum_a /
03039                    hcd->hfnum_other_samples_a : 0);
03040 
03041         DWC_PRINTF("\n");
03042         DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
03043         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03044                    hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
03045                    (hcd->hfnum_7_samples_b > 0) ?
03046                    hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
03047         DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
03048         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03049                    hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
03050                    (hcd->hfnum_0_samples_b > 0) ?
03051                    hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
03052         DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
03053         DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
03054                    hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
03055                    (hcd->hfnum_other_samples_b > 0) ?
03056                    hcd->hfnum_other_frrem_accum_b /
03057                    hcd->hfnum_other_samples_b : 0);
03058 #endif
03059 }
03060 
03061 #endif