if (dwc_otg_is_host_mode(core_if)) {
gintsts.d32 = dwc_otg_read_core_intr(core_if);
if (!gintsts.d32) {
+ DWC_PRINT("%s,GINTSTS = 0\n",__func__);
return 0;
}
* host channel interrupt and handles them appropriately. */
int32_t dwc_otg_hcd_handle_hc_intr (dwc_otg_hcd_t *_dwc_otg_hcd)
{
- int hcnum;
+ int i;
int retval = 0;
- struct list_head *qh_entry;
- dwc_otg_qh_t *qh;
haint_data_t haint;
/* Clear appropriate bits in HCINTn to clear the interrupt bit in
* GINTSTS */
haint.d32 = dwc_otg_read_host_all_channels_intr(_dwc_otg_hcd->core_if);
-
+#if 1
+ for (i = 0; i < _dwc_otg_hcd->core_if->core_params->host_channels; i++) {
+ if (haint.b2.chint & (1 << i))
+ retval |= dwc_otg_hcd_handle_hc_n_intr(_dwc_otg_hcd, i);
+ }
+#else
+ int hcnum;
+ struct list_head *qh_entry;
+ dwc_otg_qh_t *qh;
/* yk@rk 20100511
* USB Spec2.0 11.18.4
* for all periodic endpoints that have split transactions scheduled within
retval |= dwc_otg_hcd_handle_hc_n_intr (_dwc_otg_hcd, hcnum);
}
}
+#endif
return retval;
}
dwc_otg_transaction_type_e tr_type;
int free_qtd;
+ int continue_trans = 0;
+
DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n",
__func__, _hc->hc_num, _halt_status);
-
+ if((!_hc->halt_pending)||
+// (!list_empty(&_hcd->non_periodic_sched_inactive))
+ (_hcd->core_if->core_params->host_channels > 2)||
+ (!_hc->ep_is_in)||
+ (_hc->ep_type != DWC_OTG_EP_TYPE_BULK)
+ )
+ {
+ continue_trans = 1;
+ }
switch (_halt_status) {
case DWC_OTG_HC_XFER_URB_COMPLETE:
free_qtd = 1;
*/
break;
}
-
- /* Try to queue more transfers now that there's a free channel. */
- tr_type = dwc_otg_hcd_select_transactions(_hcd);
- if (tr_type != DWC_OTG_TRANSACTION_NONE) {
- dwc_otg_hcd_queue_transactions(_hcd, tr_type);
+ if(continue_trans)
+ {
+ /* Try to queue more transfers now that there's a free channel. */
+ tr_type = dwc_otg_hcd_select_transactions(_hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE) {
+ dwc_otg_hcd_queue_transactions(_hcd, tr_type);
+ }
}
+ /*
+ * Make sure the start of frame interrupt is enabled now that
+ * we know we should have queued data. The SOF interrupt
+ * handler automatically disables itself when idle to reduce
+ * the number of interrupts. See dwc_otg_hcd_handle_sof_intr()
+ * for the disable
+ */
+ dwc_modify_reg32(&_hcd->core_if->core_global_regs->gintmsk, 0,
+ DWC_SOF_INTR_MASK);
}
/**
* occurs. The core will continue transferring data.
*/
_qtd->error_count = 0;
+ //yk@rk 20100714
+ #if 1
+ if((_hcd->core_if->core_params->host_channels <= 2)
+ &&(!_hc->halt_pending))
+ dwc_otg_hc_halt(_hcd->core_if, _hc, DWC_OTG_HC_XFER_NAK);
+ #endif
goto handle_nak_done;
}
}
handle_nak_done:
+ clear_hc_int(_hc_regs,nak);
+ if(_hcd->core_if->core_params->host_channels > 2)
disable_hc_int(_hc_regs,nak);
return 1;
hcint.d32 = dwc_read_reg32(&_hc_regs->hcint);
hcintmsk.d32 = dwc_read_reg32(&_hc_regs->hcintmsk);
+ if((!hcint.b.xfercomp)&&
+ (_hcd->core_if->core_params->host_channels <= 2)&&
+ (_hc->halt_pending)&&
+ (_hc->ep_is_in)&&
+ (_hc->ep_type == DWC_OTG_EP_TYPE_BULK))
+ {
+ if(hcint.b.ack && !hcintmsk.b.ack)
+ {
+ //DWC_PRINT("Halt pending, ack!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ handle_hc_xfercomp_intr(_hcd, _hc, _hc_regs, _qtd);
+ return;
+ }
+ release_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NAK);
+ clear_hc_int(_hc_regs,chhltd);
+ return;
+ }
+
if (hcint.b.xfercomp) {
/** @todo This is here because of a possible hardware bug. Spec
* says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
* split transfers. Start splits halt on ACK.
*/
handle_hc_ack_intr(_hcd, _hc, _hc_regs, _qtd);
+ } else if(hcint.b.datatglerr){
+ DWC_PRINT("%s, DATA toggle error\n");
+ dwc_debug(1);
+ clear_hc_int(_hc_regs,chhltd);
} else {
if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
_hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
"for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
__func__, _hc->hc_num, hcint.d32,
dwc_read_reg32(&_hcd->core_if->core_global_regs->gintsts));
+ clear_hc_int(_hc_regs,chhltd);
}
}
}