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
00035 #include "dwc_otg_hcd.h"
00036 #include "dwc_otg_regs.h"
00037
00043 int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
00044 {
00045 int retval = 0;
00046
00047 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
00048 gintsts_data_t gintsts;
00049 #ifdef DEBUG
00050 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
00051 #endif
00052
00053
00054 if (dwc_otg_is_host_mode(core_if)) {
00055 gintsts.d32 = dwc_otg_read_core_intr(core_if);
00056 if (!gintsts.d32) {
00057 return 0;
00058 }
00059 #ifdef DEBUG
00060
00061 #ifndef DEBUG_SOF
00062 if (gintsts.d32 != DWC_SOF_INTR_MASK)
00063 #endif
00064 DWC_DEBUGPL(DBG_HCD, "\n");
00065 #endif
00066
00067 #ifdef DEBUG
00068 #ifndef DEBUG_SOF
00069 if (gintsts.d32 != DWC_SOF_INTR_MASK)
00070 #endif
00071 DWC_DEBUGPL(DBG_HCD,
00072 "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n",
00073 gintsts.d32);
00074 #endif
00075
00076 if (gintsts.b.sofintr) {
00077 retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
00078 }
00079 if (gintsts.b.rxstsqlvl) {
00080 retval |=
00081 dwc_otg_hcd_handle_rx_status_q_level_intr
00082 (dwc_otg_hcd);
00083 }
00084 if (gintsts.b.nptxfempty) {
00085 retval |=
00086 dwc_otg_hcd_handle_np_tx_fifo_empty_intr
00087 (dwc_otg_hcd);
00088 }
00089 if (gintsts.b.i2cintr) {
00091 }
00092 if (gintsts.b.portintr) {
00093 retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
00094 }
00095 if (gintsts.b.hcintr) {
00096 retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
00097 }
00098 if (gintsts.b.ptxfempty) {
00099 retval |=
00100 dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
00101 (dwc_otg_hcd);
00102 }
00103 #ifdef DEBUG
00104 #ifndef DEBUG_SOF
00105 if (gintsts.d32 != DWC_SOF_INTR_MASK)
00106 #endif
00107 {
00108 DWC_DEBUGPL(DBG_HCD,
00109 "DWC OTG HCD Finished Servicing Interrupts\n");
00110 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
00111 dwc_read_reg32(&global_regs->gintsts));
00112 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
00113 dwc_read_reg32(&global_regs->gintmsk));
00114 }
00115 #endif
00116
00117 #ifdef DEBUG
00118 #ifndef DEBUG_SOF
00119 if (gintsts.d32 != DWC_SOF_INTR_MASK)
00120 #endif
00121 DWC_DEBUGPL(DBG_HCD, "\n");
00122 #endif
00123
00124 }
00125
00126 return retval;
00127 }
00128
00129 #ifdef DWC_TRACK_MISSED_SOFS
00130 #warning Compiling code to track missed SOFs
00131 #define FRAME_NUM_ARRAY_SIZE 1000
00132
00135 static inline void track_missed_sofs(uint16_t curr_frame_number)
00136 {
00137 static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
00138 static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
00139 static int frame_num_idx = 0;
00140 static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
00141 static int dumped_frame_num_array = 0;
00142
00143 if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
00144 if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
00145 curr_frame_number) {
00146 frame_num_array[frame_num_idx] = curr_frame_number;
00147 last_frame_num_array[frame_num_idx++] = last_frame_num;
00148 }
00149 } else if (!dumped_frame_num_array) {
00150 int i;
00151 DWC_PRINTF("Frame Last Frame\n");
00152 DWC_PRINTF("----- ----------\n");
00153 for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
00154 DWC_PRINTF("0x%04x 0x%04x\n",
00155 frame_num_array[i], last_frame_num_array[i]);
00156 }
00157 dumped_frame_num_array = 1;
00158 }
00159 last_frame_num = curr_frame_number;
00160 }
00161 #endif
00162
00169 int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
00170 {
00171 hfnum_data_t hfnum;
00172 dwc_list_link_t *qh_entry;
00173 dwc_otg_qh_t *qh;
00174 dwc_otg_transaction_type_e tr_type;
00175 gintsts_data_t gintsts = {.d32 = 0 };
00176
00177 hfnum.d32 =
00178 dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum);
00179
00180 #ifdef DEBUG_SOF
00181 DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
00182 #endif
00183 hcd->frame_number = hfnum.b.frnum;
00184
00185 #ifdef DEBUG
00186 hcd->frrem_accum += hfnum.b.frrem;
00187 hcd->frrem_samples++;
00188 #endif
00189
00190 #ifdef DWC_TRACK_MISSED_SOFS
00191 track_missed_sofs(hcd->frame_number);
00192 #endif
00193
00194 qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
00195 while (qh_entry != &hcd->periodic_sched_inactive) {
00196 qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
00197 qh_entry = qh_entry->next;
00198 if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
00199
00200
00201
00202
00203 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
00204 &qh->qh_list_entry);
00205 }
00206 }
00207 tr_type = dwc_otg_hcd_select_transactions(hcd);
00208 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
00209 dwc_otg_hcd_queue_transactions(hcd, tr_type);
00210 }
00211
00212
00213 gintsts.b.sofintr = 1;
00214 dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
00215
00216 return 1;
00217 }
00218
00222 int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
00223 {
00224 host_grxsts_data_t grxsts;
00225 dwc_hc_t *hc = NULL;
00226
00227 DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
00228
00229 grxsts.d32 =
00230 dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
00231
00232 hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
00233
00234
00235 DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum);
00236 DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt);
00237 DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
00238 hc->data_pid_start);
00239 DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts);
00240
00241 switch (grxsts.b.pktsts) {
00242 case DWC_GRXSTS_PKTSTS_IN:
00243
00244 if (grxsts.b.bcnt > 0) {
00245 dwc_otg_read_packet(dwc_otg_hcd->core_if,
00246 hc->xfer_buff, grxsts.b.bcnt);
00247
00248
00249 hc->xfer_count += grxsts.b.bcnt;
00250 hc->xfer_buff += grxsts.b.bcnt;
00251 }
00252
00253 case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
00254 case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
00255 case DWC_GRXSTS_PKTSTS_CH_HALTED:
00256
00257 break;
00258 default:
00259 DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
00260 grxsts.b.pktsts);
00261 break;
00262 }
00263
00264 return 1;
00265 }
00266
00271 int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
00272 {
00273 DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
00274 dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
00275 DWC_OTG_TRANSACTION_NON_PERIODIC);
00276 return 1;
00277 }
00278
00283 int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
00284 {
00285 DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
00286 dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
00287 DWC_OTG_TRANSACTION_PERIODIC);
00288 return 1;
00289 }
00290
00294 int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
00295 {
00296 int retval = 0;
00297 hprt0_data_t hprt0;
00298 hprt0_data_t hprt0_modify;
00299
00300 hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0);
00301 hprt0_modify.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0);
00302
00303
00304
00305
00306 hprt0_modify.b.prtena = 0;
00307 hprt0_modify.b.prtconndet = 0;
00308 hprt0_modify.b.prtenchng = 0;
00309 hprt0_modify.b.prtovrcurrchng = 0;
00310
00311
00312
00313 if (hprt0.b.prtconndet) {
00314 DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
00315 "Port Connect Detected--\n", hprt0.d32);
00316 dwc_otg_hcd->flags.b.port_connect_status_change = 1;
00317 dwc_otg_hcd->flags.b.port_connect_status = 1;
00318 hprt0_modify.b.prtconndet = 1;
00319
00320
00321 DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
00322
00323
00324
00325 retval |= 1;
00326 }
00327
00328
00329
00330 if (hprt0.b.prtenchng) {
00331 DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
00332 "Port Enable Changed--\n", hprt0.d32);
00333 hprt0_modify.b.prtenchng = 1;
00334 if (hprt0.b.prtena == 1) {
00335 int do_reset = 0;
00336 dwc_otg_core_params_t *params =
00337 dwc_otg_hcd->core_if->core_params;
00338 dwc_otg_core_global_regs_t *global_regs =
00339 dwc_otg_hcd->core_if->core_global_regs;
00340 dwc_otg_host_if_t *host_if =
00341 dwc_otg_hcd->core_if->host_if;
00342
00343
00344
00345 if (params->host_support_fs_ls_low_power) {
00346 gusbcfg_data_t usbcfg;
00347
00348 usbcfg.d32 =
00349 dwc_read_reg32(&global_regs->gusbcfg);
00350
00351 if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
00352 || hprt0.b.prtspd ==
00353 DWC_HPRT0_PRTSPD_FULL_SPEED) {
00354
00355
00356
00357 hcfg_data_t hcfg;
00358 if (usbcfg.b.phylpwrclksel == 0) {
00359
00360 usbcfg.b.phylpwrclksel = 1;
00361 dwc_write_reg32(&global_regs->
00362 gusbcfg,
00363 usbcfg.d32);
00364 do_reset = 1;
00365 }
00366
00367 hcfg.d32 =
00368 dwc_read_reg32(&host_if->
00369 host_global_regs->hcfg);
00370
00371 if (hprt0.b.prtspd ==
00372 DWC_HPRT0_PRTSPD_LOW_SPEED
00373 && params->
00374 host_ls_low_power_phy_clk ==
00375 DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
00376 {
00377
00378 DWC_DEBUGPL(DBG_CIL,
00379 "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
00380 if (hcfg.b.fslspclksel !=
00381 DWC_HCFG_6_MHZ) {
00382 hcfg.b.fslspclksel =
00383 DWC_HCFG_6_MHZ;
00384 dwc_write_reg32
00385 (&host_if->
00386 host_global_regs->
00387 hcfg, hcfg.d32);
00388 do_reset = 1;
00389 }
00390 } else {
00391
00392 DWC_DEBUGPL(DBG_CIL,
00393 "FS_PHY programming HCFG to 48 MHz ()\n");
00394 if (hcfg.b.fslspclksel !=
00395 DWC_HCFG_48_MHZ) {
00396 hcfg.b.fslspclksel =
00397 DWC_HCFG_48_MHZ;
00398 dwc_write_reg32
00399 (&host_if->
00400 host_global_regs->
00401 hcfg, hcfg.d32);
00402 do_reset = 1;
00403 }
00404 }
00405 } else {
00406
00407
00408
00409 if (usbcfg.b.phylpwrclksel == 1) {
00410 usbcfg.b.phylpwrclksel = 0;
00411 dwc_write_reg32(&global_regs->
00412 gusbcfg,
00413 usbcfg.d32);
00414 do_reset = 1;
00415 }
00416 }
00417
00418 if (do_reset) {
00419 DWC_TASK_SCHEDULE(dwc_otg_hcd->
00420 reset_tasklet);
00421 }
00422 }
00423
00424 if (!do_reset) {
00425
00426 dwc_otg_hcd->flags.b.port_reset_change = 1;
00427 }
00428 } else {
00429 dwc_otg_hcd->flags.b.port_enable_change = 1;
00430 }
00431 retval |= 1;
00432 }
00433
00435 if (hprt0.b.prtovrcurrchng) {
00436 DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
00437 "Port Overcurrent Changed--\n", hprt0.d32);
00438 dwc_otg_hcd->flags.b.port_over_current_change = 1;
00439 hprt0_modify.b.prtovrcurrchng = 1;
00440 retval |= 1;
00441 }
00442
00443
00444 dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
00445
00446 return retval;
00447 }
00448
00453 int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
00454 {
00455 int i;
00456 int retval = 0;
00457 haint_data_t haint;
00458
00459
00460
00461
00462 haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
00463
00464 for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
00465 if (haint.b2.chint & (1 << i)) {
00466 retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
00467 }
00468 }
00469
00470 return retval;
00471 }
00472
00473
00474
00485 static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
00486 dwc_otg_hc_regs_t * hc_regs,
00487 dwc_otg_qtd_t * qtd,
00488 dwc_otg_halt_status_e halt_status,
00489 int *short_read)
00490 {
00491 hctsiz_data_t hctsiz;
00492 uint32_t length;
00493
00494 if (short_read != NULL) {
00495 *short_read = 0;
00496 }
00497 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
00498
00499 if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
00500 if (hc->ep_is_in) {
00501 length = hc->xfer_len - hctsiz.b.xfersize;
00502 if (short_read != NULL) {
00503 *short_read = (hctsiz.b.xfersize != 0);
00504 }
00505 } else if (hc->qh->do_split) {
00506 length = qtd->ssplit_out_xfer_count;
00507 } else {
00508 length = hc->xfer_len;
00509 }
00510 } else {
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 length =
00521 (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
00522 }
00523
00524 return length;
00525 }
00526
00536 static int update_urb_state_xfer_comp(dwc_hc_t * hc,
00537 dwc_otg_hc_regs_t * hc_regs,
00538 dwc_otg_hcd_urb_t * urb,
00539 dwc_otg_qtd_t * qtd)
00540 {
00541 int xfer_done = 0;
00542 int short_read = 0;
00543
00544 int xfer_length;
00545
00546 xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
00547 DWC_OTG_HC_XFER_COMPLETE,
00548 &short_read);
00549
00550
00551
00552 if (hc->align_buff && xfer_length && hc->ep_is_in) {
00553 dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, xfer_length);
00554 }
00555
00556 urb->actual_length += xfer_length;
00557
00558 if(xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
00559 (urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) &&
00560 !(urb->length % hc->max_packet)) {
00561 xfer_done = 0;
00562 } else if (short_read || urb->actual_length == urb->length) {
00563 xfer_done = 1;
00564 urb->status = 0;
00565 }
00566
00567 #ifdef DEBUG
00568 {
00569 hctsiz_data_t hctsiz;
00570 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
00571 DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
00572 __func__, (hc->ep_is_in ? "IN" : "OUT"),
00573 hc->hc_num);
00574 DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len);
00575 DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n",
00576 hctsiz.b.xfersize);
00577 DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
00578 urb->length);
00579 DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
00580 urb->actual_length);
00581 DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n",
00582 short_read, xfer_done);
00583 }
00584 #endif
00585
00586 return xfer_done;
00587 }
00588
00589
00590
00591
00592
00593
00594 void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
00595 dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
00596 {
00597 hctsiz_data_t hctsiz;
00598 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
00599
00600 if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
00601 dwc_otg_qh_t *qh = hc->qh;
00602 if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
00603 qh->data_toggle = DWC_OTG_HC_PID_DATA0;
00604 } else {
00605 qh->data_toggle = DWC_OTG_HC_PID_DATA1;
00606 }
00607 } else {
00608 if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
00609 qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
00610 } else {
00611 qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
00612 }
00613 }
00614 }
00615
00625 static dwc_otg_halt_status_e
00626 update_isoc_urb_state(dwc_otg_hcd_t * hcd,
00627 dwc_hc_t * hc,
00628 dwc_otg_hc_regs_t * hc_regs,
00629 dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
00630 {
00631 dwc_otg_hcd_urb_t *urb = qtd->urb;
00632 dwc_otg_halt_status_e ret_val = halt_status;
00633 struct dwc_otg_hcd_iso_packet_desc *frame_desc;
00634
00635 frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
00636 switch (halt_status) {
00637 case DWC_OTG_HC_XFER_COMPLETE:
00638 frame_desc->status = 0;
00639 frame_desc->actual_length =
00640 get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
00641
00642
00643 if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
00644 dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
00645 hc->qh->dw_align_buf, frame_desc->actual_length);
00646 }
00647
00648 break;
00649 case DWC_OTG_HC_XFER_FRAME_OVERRUN:
00650 urb->error_count++;
00651 if (hc->ep_is_in) {
00652 frame_desc->status = -DWC_E_NO_STREAM_RES;
00653 } else {
00654 frame_desc->status = -DWC_E_COMMUNICATION;
00655 }
00656 frame_desc->actual_length = 0;
00657 break;
00658 case DWC_OTG_HC_XFER_BABBLE_ERR:
00659 urb->error_count++;
00660 frame_desc->status = -DWC_E_OVERFLOW;
00661
00662 break;
00663 case DWC_OTG_HC_XFER_XACT_ERR:
00664 urb->error_count++;
00665 frame_desc->status = -DWC_E_PROTOCOL;
00666 frame_desc->actual_length =
00667 get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
00668
00669
00670 if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
00671 dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
00672 hc->qh->dw_align_buf, frame_desc->actual_length);
00673 }
00674
00675 if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
00676 hc->ep_is_in && hcd->core_if->dma_enable) {
00677 qtd->complete_split = 0;
00678 qtd->isoc_split_offset = 0;
00679 }
00680
00681 break;
00682 default:
00683 DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
00684 break;
00685 }
00686 if (++qtd->isoc_frame_index == urb->packet_count) {
00687
00688
00689
00690
00691 hcd->fops->complete(hcd, urb->priv, urb, 0);
00692 ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
00693 } else {
00694 ret_val = DWC_OTG_HC_XFER_COMPLETE;
00695 }
00696 return ret_val;
00697 }
00698
00706 static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
00707 {
00708 int continue_split = 0;
00709 dwc_otg_qtd_t *qtd;
00710
00711 DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
00712
00713 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
00714
00715 if (qtd->complete_split) {
00716 continue_split = 1;
00717 } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
00718 qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
00719 continue_split = 1;
00720 }
00721
00722 if (free_qtd) {
00723 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
00724 continue_split = 0;
00725 }
00726
00727 qh->channel = NULL;
00728 dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
00729 }
00730
00742 static void release_channel(dwc_otg_hcd_t * hcd,
00743 dwc_hc_t * hc,
00744 dwc_otg_qtd_t * qtd,
00745 dwc_otg_halt_status_e halt_status)
00746 {
00747 dwc_otg_transaction_type_e tr_type;
00748 int free_qtd;
00749
00750 DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n",
00751 __func__, hc->hc_num, halt_status);
00752
00753 switch (halt_status) {
00754 case DWC_OTG_HC_XFER_URB_COMPLETE:
00755 free_qtd = 1;
00756 break;
00757 case DWC_OTG_HC_XFER_AHB_ERR:
00758 case DWC_OTG_HC_XFER_STALL:
00759 case DWC_OTG_HC_XFER_BABBLE_ERR:
00760 free_qtd = 1;
00761 break;
00762 case DWC_OTG_HC_XFER_XACT_ERR:
00763 if (qtd->error_count >= 3) {
00764 DWC_DEBUGPL(DBG_HCDV,
00765 " Complete URB with transaction error\n");
00766 free_qtd = 1;
00767 qtd->urb->status = -DWC_E_PROTOCOL;
00768 hcd->fops->complete(hcd, qtd->urb->priv,
00769 qtd->urb, -DWC_E_PROTOCOL);
00770 } else {
00771 free_qtd = 0;
00772 }
00773 break;
00774 case DWC_OTG_HC_XFER_URB_DEQUEUE:
00775
00776
00777
00778
00779
00780 goto cleanup;
00781 case DWC_OTG_HC_XFER_NO_HALT_STATUS:
00782 free_qtd = 0;
00783 break;
00784 default:
00785 free_qtd = 0;
00786 break;
00787 }
00788
00789 deactivate_qh(hcd, hc->qh, free_qtd);
00790
00791 cleanup:
00792
00793
00794
00795
00796
00797 dwc_otg_hc_cleanup(hcd->core_if, hc);
00798 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
00799
00800 switch (hc->ep_type) {
00801 case DWC_OTG_EP_TYPE_CONTROL:
00802 case DWC_OTG_EP_TYPE_BULK:
00803 hcd->non_periodic_channels--;
00804 break;
00805
00806 default:
00807
00808
00809
00810
00811
00812 break;
00813 }
00814
00815
00816 tr_type = dwc_otg_hcd_select_transactions(hcd);
00817 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
00818 dwc_otg_hcd_queue_transactions(hcd, tr_type);
00819 }
00820 }
00821
00822
00833 static void halt_channel(dwc_otg_hcd_t * hcd,
00834 dwc_hc_t * hc,
00835 dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
00836 {
00837 if (hcd->core_if->dma_enable) {
00838 release_channel(hcd, hc, qtd, halt_status);
00839 return;
00840 }
00841
00842
00843 dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
00844
00845 if (hc->halt_on_queue) {
00846 gintmsk_data_t gintmsk = {.d32 = 0 };
00847 dwc_otg_core_global_regs_t *global_regs;
00848 global_regs = hcd->core_if->core_global_regs;
00849
00850 if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
00851 hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
00852
00853
00854
00855
00856
00857 gintmsk.b.nptxfempty = 1;
00858 dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32);
00859 } else {
00860
00861
00862
00863
00864
00865
00866 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
00867 &hc->qh->qh_list_entry);
00868
00869
00870
00871
00872
00873
00874 gintmsk.b.ptxfempty = 1;
00875 dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32);
00876 }
00877 }
00878 }
00879
00885 static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
00886 dwc_hc_t * hc,
00887 dwc_otg_hc_regs_t * hc_regs,
00888 dwc_otg_qtd_t * qtd,
00889 dwc_otg_halt_status_e halt_status)
00890 {
00891 hcint_data_t hcint;
00892
00893 qtd->error_count = 0;
00894
00895 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
00896 if (hcint.b.nyet) {
00897
00898
00899
00900
00901
00902 hc->qh->ping_state = 1;
00903 clear_hc_int(hc_regs, nyet);
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 if (hc->ep_is_in) {
00917
00918
00919
00920
00921
00922 halt_channel(hcd, hc, qtd, halt_status);
00923 } else {
00924
00925
00926
00927
00928 release_channel(hcd, hc, qtd, halt_status);
00929 }
00930 }
00931
00937 static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
00938 dwc_hc_t * hc,
00939 dwc_otg_hc_regs_t * hc_regs,
00940 dwc_otg_qtd_t * qtd,
00941 dwc_otg_halt_status_e halt_status)
00942 {
00943 hctsiz_data_t hctsiz;
00944 qtd->error_count = 0;
00945
00946 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
00947 if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
00948
00949 release_channel(hcd, hc, qtd, halt_status);
00950 } else {
00951
00952 halt_channel(hcd, hc, qtd, halt_status);
00953 }
00954 }
00955
00956 static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
00957 dwc_hc_t * hc,
00958 dwc_otg_hc_regs_t * hc_regs,
00959 dwc_otg_qtd_t * qtd)
00960 {
00961 uint32_t len;
00962 struct dwc_otg_hcd_iso_packet_desc *frame_desc;
00963 frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
00964
00965 len = get_actual_xfer_length(hc, hc_regs, qtd,
00966 DWC_OTG_HC_XFER_COMPLETE,
00967 NULL);
00968
00969 if (!len) {
00970 qtd->complete_split = 0;
00971 qtd->isoc_split_offset = 0;
00972 return 0;
00973 }
00974 frame_desc->actual_length += len;
00975
00976 if (hc->align_buff && len)
00977 dwc_memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset,
00978 hc->qh->dw_align_buf,
00979 len);
00980 qtd->isoc_split_offset += len;
00981
00982 if (frame_desc->length == frame_desc->actual_length) {
00983 frame_desc->status = 0;
00984 qtd->isoc_frame_index++;
00985 qtd->complete_split = 0;
00986 qtd->isoc_split_offset = 0;
00987 }
00988
00989 if (qtd->isoc_frame_index == qtd->urb->packet_count) {
00990 hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
00991 release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
00992 } else {
00993 release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
00994 }
00995
00996 return 1;
00997 }
01002 static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
01003 dwc_hc_t * hc,
01004 dwc_otg_hc_regs_t * hc_regs,
01005 dwc_otg_qtd_t * qtd)
01006 {
01007 int urb_xfer_done;
01008 dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
01009 dwc_otg_hcd_urb_t *urb = qtd->urb;
01010 int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
01011
01012 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01013 "Transfer Complete--\n", hc->hc_num);
01014
01015 if (hcd->core_if->dma_desc_enable) {
01016 dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
01017 if (pipe_type == UE_ISOCHRONOUS) {
01018
01019 clear_hc_int(hc_regs, xfercomp);
01020 return 1;
01021 }
01022 goto handle_xfercomp_done;
01023 }
01024
01025
01026
01027
01028
01029 if (hc->qh->do_split) {
01030 if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in && hcd->core_if->dma_enable) {
01031 if (qtd->complete_split && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, qtd))
01032 goto handle_xfercomp_done;
01033 }
01034 else {
01035 qtd->complete_split = 0;
01036 }
01037 }
01038
01039
01040 switch (pipe_type) {
01041 case UE_CONTROL:
01042 switch (qtd->control_phase) {
01043 case DWC_OTG_CONTROL_SETUP:
01044 if (urb->length > 0) {
01045 qtd->control_phase = DWC_OTG_CONTROL_DATA;
01046 } else {
01047 qtd->control_phase = DWC_OTG_CONTROL_STATUS;
01048 }
01049 DWC_DEBUGPL(DBG_HCDV,
01050 " Control setup transaction done\n");
01051 halt_status = DWC_OTG_HC_XFER_COMPLETE;
01052 break;
01053 case DWC_OTG_CONTROL_DATA:{
01054 urb_xfer_done =
01055 update_urb_state_xfer_comp(hc, hc_regs, urb,
01056 qtd);
01057 if (urb_xfer_done) {
01058 qtd->control_phase =
01059 DWC_OTG_CONTROL_STATUS;
01060 DWC_DEBUGPL(DBG_HCDV,
01061 " Control data transfer done\n");
01062 } else {
01063 dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
01064 }
01065 halt_status = DWC_OTG_HC_XFER_COMPLETE;
01066 break;
01067 }
01068 case DWC_OTG_CONTROL_STATUS:
01069 DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n");
01070 if (urb->status == -DWC_E_IN_PROGRESS) {
01071 urb->status = 0;
01072 }
01073 hcd->fops->complete(hcd, urb->priv, urb, urb->status);
01074 halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
01075 break;
01076 }
01077
01078 complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
01079 break;
01080 case UE_BULK:
01081 DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n");
01082 urb_xfer_done =
01083 update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
01084 if (urb_xfer_done) {
01085 hcd->fops->complete(hcd, urb->priv, urb, urb->status);
01086 halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
01087 } else {
01088 halt_status = DWC_OTG_HC_XFER_COMPLETE;
01089 }
01090
01091 dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
01092 complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
01093 break;
01094 case UE_INTERRUPT:
01095 DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n");
01096 update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
01097
01098
01099
01100
01101
01102 hcd->fops->complete(hcd, urb->priv, urb, urb->status);
01103 dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
01104 complete_periodic_xfer(hcd, hc, hc_regs, qtd,
01105 DWC_OTG_HC_XFER_URB_COMPLETE);
01106 break;
01107 case UE_ISOCHRONOUS:
01108 DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n");
01109 if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
01110 halt_status =
01111 update_isoc_urb_state(hcd, hc, hc_regs, qtd,
01112 DWC_OTG_HC_XFER_COMPLETE);
01113 }
01114 complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
01115 break;
01116 }
01117
01118 handle_xfercomp_done:
01119 disable_hc_int(hc_regs, xfercompl);
01120
01121 return 1;
01122 }
01123
01128 static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
01129 dwc_hc_t * hc,
01130 dwc_otg_hc_regs_t * hc_regs,
01131 dwc_otg_qtd_t * qtd)
01132 {
01133 dwc_otg_hcd_urb_t *urb = qtd->urb;
01134 int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
01135
01136 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01137 "STALL Received--\n", hc->hc_num);
01138
01139 if (hcd->core_if->dma_desc_enable) {
01140 dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
01141 goto handle_stall_done;
01142 }
01143
01144 if (pipe_type == UE_CONTROL) {
01145 hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
01146 }
01147
01148 if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
01149 hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
01150
01151
01152
01153
01154
01155
01156
01157 hc->qh->data_toggle = 0;
01158 }
01159
01160 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
01161
01162 handle_stall_done:
01163 disable_hc_int(hc_regs, stall);
01164
01165 return 1;
01166 }
01167
01168
01169
01170
01171
01172
01173
01174 static void update_urb_state_xfer_intr(dwc_hc_t * hc,
01175 dwc_otg_hc_regs_t * hc_regs,
01176 dwc_otg_hcd_urb_t * urb,
01177 dwc_otg_qtd_t * qtd,
01178 dwc_otg_halt_status_e halt_status)
01179 {
01180 uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
01181 halt_status, NULL);
01182
01183 if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
01184 dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, bytes_transferred);
01185 }
01186
01187 urb->actual_length += bytes_transferred;
01188
01189 #ifdef DEBUG
01190 {
01191 hctsiz_data_t hctsiz;
01192 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
01193 DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
01194 __func__, (hc->ep_is_in ? "IN" : "OUT"),
01195 hc->hc_num);
01196 DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n",
01197 hc->start_pkt_count);
01198 DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
01199 DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet);
01200 DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n",
01201 bytes_transferred);
01202 DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
01203 urb->actual_length);
01204 DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
01205 urb->length);
01206 }
01207 #endif
01208 }
01209
01214 static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
01215 dwc_hc_t * hc,
01216 dwc_otg_hc_regs_t * hc_regs,
01217 dwc_otg_qtd_t * qtd)
01218 {
01219 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01220 "NAK Received--\n", hc->hc_num);
01221
01222
01223
01224
01225
01226 if (hc->do_split) {
01227 if (hc->complete_split) {
01228 qtd->error_count = 0;
01229 }
01230 qtd->complete_split = 0;
01231 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
01232 goto handle_nak_done;
01233 }
01234
01235 switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
01236 case UE_CONTROL:
01237 case UE_BULK:
01238 if (hcd->core_if->dma_enable && hc->ep_is_in) {
01239
01240
01241
01242
01243
01244
01245 qtd->error_count = 0;
01246 goto handle_nak_done;
01247 }
01248
01249
01250
01251
01252
01253
01254 qtd->error_count = 0;
01255
01256 if (!hc->qh->ping_state) {
01257 update_urb_state_xfer_intr(hc, hc_regs,
01258 qtd->urb, qtd,
01259 DWC_OTG_HC_XFER_NAK);
01260 dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
01261
01262 if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
01263 hc->qh->ping_state = 1;
01264 }
01265
01266
01267
01268
01269
01270
01271 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
01272 break;
01273 case UE_INTERRUPT:
01274 qtd->error_count = 0;
01275 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
01276 break;
01277 case UE_ISOCHRONOUS:
01278
01279 DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
01280 break;
01281 }
01282
01283 handle_nak_done:
01284 disable_hc_int(hc_regs, nak);
01285
01286 return 1;
01287 }
01288
01294 static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
01295 dwc_hc_t * hc,
01296 dwc_otg_hc_regs_t * hc_regs,
01297 dwc_otg_qtd_t * qtd)
01298 {
01299 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01300 "ACK Received--\n", hc->hc_num);
01301
01302 if (hc->do_split) {
01303
01304
01305
01306
01307 if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
01308 qtd->ssplit_out_xfer_count = hc->xfer_len;
01309 }
01310 if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
01311
01312 qtd->complete_split = 1;
01313 }
01314
01315
01316 if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
01317 switch (hc->xact_pos) {
01318 case DWC_HCSPLIT_XACTPOS_ALL:
01319 break;
01320 case DWC_HCSPLIT_XACTPOS_END:
01321 qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
01322 qtd->isoc_split_offset = 0;
01323 break;
01324 case DWC_HCSPLIT_XACTPOS_BEGIN:
01325 case DWC_HCSPLIT_XACTPOS_MID:
01326
01327
01328
01329
01330
01331 {
01332 struct dwc_otg_hcd_iso_packet_desc
01333 *frame_desc;
01334
01335 frame_desc =
01336 &qtd->urb->iso_descs[qtd->
01337 isoc_frame_index];
01338 qtd->isoc_split_offset += 188;
01339
01340 if ((frame_desc->length -
01341 qtd->isoc_split_offset) <= 188) {
01342 qtd->isoc_split_pos =
01343 DWC_HCSPLIT_XACTPOS_END;
01344 } else {
01345 qtd->isoc_split_pos =
01346 DWC_HCSPLIT_XACTPOS_MID;
01347 }
01348
01349 }
01350 break;
01351 }
01352 } else {
01353 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
01354 }
01355 } else {
01356 qtd->error_count = 0;
01357
01358 if (hc->qh->ping_state) {
01359 hc->qh->ping_state = 0;
01360
01361
01362
01363
01364
01365
01366
01367 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
01368 }
01369 }
01370
01371
01372
01373
01374
01375
01376 disable_hc_int(hc_regs, ack);
01377
01378 return 1;
01379 }
01380
01388 static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
01389 dwc_hc_t * hc,
01390 dwc_otg_hc_regs_t * hc_regs,
01391 dwc_otg_qtd_t * qtd)
01392 {
01393 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01394 "NYET Received--\n", hc->hc_num);
01395
01396
01397
01398
01399
01400 if (hc->do_split && hc->complete_split) {
01401 if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hcd->core_if->dma_enable) {
01402 qtd->complete_split = 0;
01403 qtd->isoc_split_offset = 0;
01404 if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
01405 hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
01406 release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
01407 }
01408 else
01409 release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
01410 goto handle_nyet_done;
01411 }
01412
01413 if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
01414 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
01415 int frnum = dwc_otg_hcd_get_frame_number(hcd);
01416
01417 if (dwc_full_frame_num(frnum) !=
01418 dwc_full_frame_num(hc->qh->sched_frame)) {
01419
01420
01421
01422
01423 #if 0
01424
01430 qtd->error_count++;
01431 #endif
01432 qtd->complete_split = 0;
01433 halt_channel(hcd, hc, qtd,
01434 DWC_OTG_HC_XFER_XACT_ERR);
01436 goto handle_nyet_done;
01437 }
01438 }
01439
01440 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
01441 goto handle_nyet_done;
01442 }
01443
01444 hc->qh->ping_state = 1;
01445 qtd->error_count = 0;
01446
01447 update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
01448 DWC_OTG_HC_XFER_NYET);
01449 dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
01450
01451
01452
01453
01454
01455 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
01456
01457 handle_nyet_done:
01458 disable_hc_int(hc_regs, nyet);
01459 return 1;
01460 }
01461
01466 static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
01467 dwc_hc_t * hc,
01468 dwc_otg_hc_regs_t * hc_regs,
01469 dwc_otg_qtd_t * qtd)
01470 {
01471 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01472 "Babble Error--\n", hc->hc_num);
01473
01474 if (hcd->core_if->dma_desc_enable) {
01475 dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_BABBLE_ERR);
01476 goto handle_babble_done;
01477 }
01478
01479 if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
01480 hcd->fops->complete(hcd, qtd->urb->priv,
01481 qtd->urb, -DWC_E_OVERFLOW);
01482 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
01483 } else {
01484 dwc_otg_halt_status_e halt_status;
01485 halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
01486 DWC_OTG_HC_XFER_BABBLE_ERR);
01487 halt_channel(hcd, hc, qtd, halt_status);
01488 }
01489
01490 handle_babble_done:
01491 disable_hc_int(hc_regs, bblerr);
01492 return 1;
01493 }
01494
01499 static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
01500 dwc_hc_t * hc,
01501 dwc_otg_hc_regs_t * hc_regs,
01502 dwc_otg_qtd_t * qtd)
01503 {
01504 hcchar_data_t hcchar;
01505 hcsplt_data_t hcsplt;
01506 hctsiz_data_t hctsiz;
01507 uint32_t hcdma;
01508 char *pipetype, *speed;
01509
01510 dwc_otg_hcd_urb_t *urb = qtd->urb;
01511
01512 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01513 "AHB Error--\n", hc->hc_num);
01514
01515 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01516 hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
01517 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
01518 hcdma = dwc_read_reg32(&hc_regs->hcdma);
01519
01520 DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
01521 DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
01522 DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
01523 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
01524 DWC_ERROR(" Device address: %d\n",
01525 dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
01526 DWC_ERROR(" Endpoint: %d, %s\n",
01527 dwc_otg_hcd_get_ep_num(&urb->pipe_info),
01528 (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
01529
01530
01531 switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
01532 case UE_CONTROL:
01533 pipetype = "CONTROL";
01534 break;
01535 case UE_BULK:
01536 pipetype = "BULK";
01537 break;
01538 case UE_INTERRUPT:
01539 pipetype = "INTERRUPT";
01540 break;
01541 case UE_ISOCHRONOUS:
01542 pipetype = "ISOCHRONOUS";
01543 break;
01544 default:
01545 pipetype = "UNKNOWN";
01546 break;
01547 }
01548
01549 DWC_ERROR(" Endpoint type: %s\n", pipetype);
01550
01551 switch (hc->speed) {
01552 case DWC_OTG_EP_SPEED_HIGH:
01553 speed = "HIGH";
01554 break;
01555 case DWC_OTG_EP_SPEED_FULL:
01556 speed = "FULL";
01557 break;
01558 case DWC_OTG_EP_SPEED_LOW:
01559 speed = "LOW";
01560 break;
01561 default:
01562 speed = "UNKNOWN";
01563 break;
01564 };
01565
01566 DWC_ERROR(" Speed: %s\n", speed);
01567
01568 DWC_ERROR(" Max packet size: %d\n",
01569 dwc_otg_hcd_get_mps(&urb->pipe_info));
01570 DWC_ERROR(" Data buffer length: %d\n", urb->length);
01571 DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n",
01572 urb->buf, (void *)urb->dma);
01573 DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n",
01574 urb->setup_packet, (void *)urb->setup_dma);
01575 DWC_ERROR(" Interval: %d\n", urb->interval);
01576
01577
01578 if (hcd->core_if->dma_desc_enable) {
01579 dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_AHB_ERR);
01580 goto handle_ahberr_done;
01581 }
01582
01583 hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
01584
01585
01586
01587
01588
01589 dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
01590 handle_ahberr_done:
01591 disable_hc_int(hc_regs, ahberr);
01592 return 1;
01593 }
01594
01599 static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
01600 dwc_hc_t * hc,
01601 dwc_otg_hc_regs_t * hc_regs,
01602 dwc_otg_qtd_t * qtd)
01603 {
01604 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01605 "Transaction Error--\n", hc->hc_num);
01606
01607 if (hcd->core_if->dma_desc_enable) {
01608 dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_XACT_ERR);
01609 goto handle_xacterr_done;
01610 }
01611
01612 switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
01613 case UE_CONTROL:
01614 case UE_BULK:
01615 qtd->error_count++;
01616 if (!hc->qh->ping_state) {
01617
01618 update_urb_state_xfer_intr(hc, hc_regs,
01619 qtd->urb, qtd,
01620 DWC_OTG_HC_XFER_XACT_ERR);
01621 dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
01622 if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
01623 hc->qh->ping_state = 1;
01624 }
01625 }
01626
01627
01628
01629
01630
01631 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
01632 break;
01633 case UE_INTERRUPT:
01634 qtd->error_count++;
01635 if (hc->do_split && hc->complete_split) {
01636 qtd->complete_split = 0;
01637 }
01638 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
01639 break;
01640 case UE_ISOCHRONOUS:
01641 {
01642 dwc_otg_halt_status_e halt_status;
01643 halt_status =
01644 update_isoc_urb_state(hcd, hc, hc_regs, qtd,
01645 DWC_OTG_HC_XFER_XACT_ERR);
01646
01647 halt_channel(hcd, hc, qtd, halt_status);
01648 }
01649 break;
01650 }
01651 handle_xacterr_done:
01652 disable_hc_int(hc_regs, xacterr);
01653
01654 return 1;
01655 }
01656
01661 static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
01662 dwc_hc_t * hc,
01663 dwc_otg_hc_regs_t * hc_regs,
01664 dwc_otg_qtd_t * qtd)
01665 {
01666 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01667 "Frame Overrun--\n", hc->hc_num);
01668
01669 switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
01670 case UE_CONTROL:
01671 case UE_BULK:
01672 break;
01673 case UE_INTERRUPT:
01674 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
01675 break;
01676 case UE_ISOCHRONOUS:
01677 {
01678 dwc_otg_halt_status_e halt_status;
01679 halt_status =
01680 update_isoc_urb_state(hcd, hc, hc_regs, qtd,
01681 DWC_OTG_HC_XFER_FRAME_OVERRUN);
01682
01683 halt_channel(hcd, hc, qtd, halt_status);
01684 }
01685 break;
01686 }
01687
01688 disable_hc_int(hc_regs, frmovrun);
01689
01690 return 1;
01691 }
01692
01697 static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
01698 dwc_hc_t * hc,
01699 dwc_otg_hc_regs_t * hc_regs,
01700 dwc_otg_qtd_t * qtd)
01701 {
01702 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01703 "Data Toggle Error--\n", hc->hc_num);
01704
01705 if (hc->ep_is_in) {
01706 qtd->error_count = 0;
01707 } else {
01708 DWC_ERROR("Data Toggle Error on OUT transfer,"
01709 "channel %d\n", hc->hc_num);
01710 }
01711
01712 disable_hc_int(hc_regs, datatglerr);
01713
01714 return 1;
01715 }
01716
01717 #ifdef DEBUG
01718
01724 static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
01725 dwc_hc_t * hc,
01726 dwc_otg_hc_regs_t * hc_regs,
01727 dwc_otg_qtd_t * qtd)
01728 {
01729 hcchar_data_t hcchar;
01730 hctsiz_data_t hctsiz;
01731 hcint_data_t hcint;
01732 hcintmsk_data_t hcintmsk;
01733 hcsplt_data_t hcsplt;
01734
01735 if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
01736
01737
01738
01739
01740 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01741 hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
01742 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01743 hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
01744 hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
01745 DWC_WARN
01746 ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
01747 "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
01748 "hcint 0x%08x, hcintmsk 0x%08x, "
01749 "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
01750 hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
01751 hcintmsk.d32, hcsplt.d32, qtd->complete_split);
01752
01753 DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
01754 __func__, hc->hc_num);
01755 DWC_WARN("\n");
01756 clear_hc_int(hc_regs, chhltd);
01757 return 0;
01758 }
01759
01760
01761
01762
01763
01764
01765 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01766 if (hcchar.b.chdis) {
01767 DWC_WARN("%s: hcchar.chdis set unexpectedly, "
01768 "hcchar 0x%08x, trying to halt again\n",
01769 __func__, hcchar.d32);
01770 clear_hc_int(hc_regs, chhltd);
01771 hc->halt_pending = 0;
01772 halt_channel(hcd, hc, qtd, hc->halt_status);
01773 return 0;
01774 }
01775
01776 return 1;
01777 }
01778 #endif
01779
01784 static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
01785 dwc_hc_t * hc,
01786 dwc_otg_hc_regs_t * hc_regs,
01787 dwc_otg_qtd_t * qtd)
01788 {
01789 hcint_data_t hcint;
01790 hcintmsk_data_t hcintmsk;
01791 int out_nak_enh = 0;
01792
01793
01794
01795
01796 if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
01797 if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
01798 (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
01799 hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
01800 out_nak_enh = 1;
01801 }
01802 }
01803
01804 if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
01805 (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR && !hcd->core_if->dma_desc_enable)) {
01806
01807
01808
01809
01810
01811
01812 if (hcd->core_if->dma_desc_enable)
01813 dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, hc->halt_status);
01814 else
01815 release_channel(hcd, hc, qtd, hc->halt_status);
01816 return;
01817 }
01818
01819
01820 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01821 hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
01822
01823 if (hcint.b.xfercomp) {
01830 if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
01831 handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
01832 }
01833 handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
01834 } else if (hcint.b.stall) {
01835 handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
01836 } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
01837 if (out_nak_enh) {
01838 if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
01839 DWC_DEBUG("XactErr with NYET/NAK/ACK\n");
01840 qtd->error_count = 0;
01841 } else {
01842 DWC_DEBUG("XactErr without NYET/NAK/ACK\n");
01843 }
01844 }
01845
01846
01847
01848
01849
01850
01851 handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
01852 } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
01853 handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
01854 } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
01855 handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
01856 } else if (hcint.b.bblerr) {
01857 handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
01858 } else if (hcint.b.frmovrun) {
01859 handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
01860 } else if (!out_nak_enh) {
01861 if (hcint.b.nyet) {
01862
01863
01864
01865
01866
01867 handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
01868 } else if (hcint.b.nak && !hcintmsk.b.nak) {
01869
01870
01871
01872
01873
01874
01875
01876 handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
01877 } else if (hcint.b.ack && !hcintmsk.b.ack) {
01878
01879
01880
01881
01882
01883
01884 handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
01885 } else {
01886 if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
01887 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
01888
01889
01890
01891
01892
01893
01894 #ifdef DEBUG
01895 DWC_PRINTF
01896 ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
01897 __func__, hc->hc_num);
01898 #endif
01899 halt_channel(hcd, hc, qtd,
01900 DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
01901 } else {
01902 DWC_ERROR
01903 ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
01904 "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
01905 __func__, hc->hc_num, hcint.d32,
01906 dwc_read_reg32(&hcd->core_if->
01907 core_global_regs->gintsts));
01908 }
01909
01910 }
01911 } else {
01912 DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
01913 hcint.d32);
01914 }
01915 }
01916
01928 static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
01929 dwc_hc_t * hc,
01930 dwc_otg_hc_regs_t * hc_regs,
01931 dwc_otg_qtd_t * qtd)
01932 {
01933 DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
01934 "Channel Halted--\n", hc->hc_num);
01935
01936 if (hcd->core_if->dma_enable) {
01937 handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
01938 } else {
01939 #ifdef DEBUG
01940 if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
01941 return 1;
01942 }
01943 #endif
01944 release_channel(hcd, hc, qtd, hc->halt_status);
01945 }
01946
01947 return 1;
01948 }
01949
01951 int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
01952 {
01953 int retval = 0;
01954 hcint_data_t hcint;
01955 hcintmsk_data_t hcintmsk;
01956 dwc_hc_t *hc;
01957 dwc_otg_hc_regs_t *hc_regs;
01958 dwc_otg_qtd_t *qtd;
01959
01960 DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
01961
01962 hc = dwc_otg_hcd->hc_ptr_array[num];
01963 hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
01964 qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
01965
01966 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01967 hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
01968 DWC_DEBUGPL(DBG_HCDV,
01969 " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
01970 hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
01971 hcint.d32 = hcint.d32 & hcintmsk.d32;
01972
01973 if (!dwc_otg_hcd->core_if->dma_enable) {
01974 if (hcint.b.chhltd && hcint.d32 != 0x2) {
01975 hcint.b.chhltd = 0;
01976 }
01977 }
01978
01979 if (hcint.b.xfercomp) {
01980 retval |=
01981 handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
01982
01983
01984
01985
01986
01987 hcint.b.nyet = 0;
01988 }
01989 if (hcint.b.chhltd) {
01990 retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
01991 }
01992 if (hcint.b.ahberr) {
01993 retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
01994 }
01995 if (hcint.b.stall) {
01996 retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
01997 }
01998 if (hcint.b.nak) {
01999 retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02000 }
02001 if (hcint.b.ack) {
02002 retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02003 }
02004 if (hcint.b.nyet) {
02005 retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02006 }
02007 if (hcint.b.xacterr) {
02008 retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02009 }
02010 if (hcint.b.bblerr) {
02011 retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02012 }
02013 if (hcint.b.frmovrun) {
02014 retval |=
02015 handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02016 }
02017 if (hcint.b.datatglerr) {
02018 retval |=
02019 handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
02020 }
02021
02022 return retval;
02023 }
02024
02025 #endif