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