DWC_FREE(dwc_otg_hcd);
}
-int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
-
int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
{
struct device *dev = dwc_otg_hcd_to_dev(hcd);
/**
* fiq_fsm_transaction_suitable() - Test a QH for compatibility with the FIQ
+ * @hcd: Pointer to the dwc_otg_hcd struct
* @qh: pointer to the endpoint's queue head
*
* Transaction start/end control flow is grafted onto the existing dwc_otg
* Returns: 0 for unsuitable, 1 implies the FIQ can be enabled for this transaction.
*/
-int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh)
+int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
{
+ /* There is little benefit in using the FIQ to perform transfers if
+ * the root port is not in high-speed mode.
+ */
+ if (hcd->flags.b.port_speed != DWC_HPRT0_PRTSPD_HIGH_SPEED)
+ return 0;
+
if (qh->do_split) {
switch (qh->ep_type) {
case UE_CONTROL:
continue;
}
- if (fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) {
+ if (fiq_fsm_enable && fiq_fsm_transaction_suitable(hcd, qh)) {
if (qh->do_split)
fiq_fsm_queue_split_transaction(hcd, qh);
else
qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
qh_list_entry);
- if(fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) {
+ if(fiq_fsm_enable && fiq_fsm_transaction_suitable(hcd, qh)) {
fiq_fsm_queue_split_transaction(hcd, qh);
} else {
status = queue_transaction(hcd, qh->channel,
unsigned port_suspend_change:1;
unsigned port_over_current_change:1;
unsigned port_l1_change:1;
- unsigned reserved:26;
+ unsigned port_speed:2;
+ unsigned reserved:24;
} b;
} flags;
void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
extern int fiq_fsm_queue_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
-extern int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh);
+extern int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
extern void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num);
/** @} */
return frame & 0x7;
}
+extern void init_hcd_usecs(dwc_otg_hcd_t *_hcd);
+
void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
dwc_otg_hc_regs_t * hc_regs,
dwc_otg_qtd_t * qtd);
dwc_otg_host_if_t *host_if =
dwc_otg_hcd->core_if->host_if;
+ dwc_otg_hcd->flags.b.port_speed = hprt0.b.prtspd;
+ if (microframe_schedule)
+ init_hcd_usecs(dwc_otg_hcd);
+
/* Every time when port enables calculate
* HFIR.FrInterval
*/
/*
* called from dwc_otg_hcd.c:dwc_otg_hcd_init
*/
-int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
+void init_hcd_usecs(dwc_otg_hcd_t *_hcd)
{
int i;
- for (i=0; i<8; i++) {
- _hcd->frame_usecs[i] = max_uframe_usecs[i];
+ if (_hcd->flags.b.port_speed == DWC_HPRT0_PRTSPD_FULL_SPEED) {
+ _hcd->frame_usecs[0] = 900;
+ for (i = 1; i < 8; i++)
+ _hcd->frame_usecs[i] = 0;
+ } else {
+ for (i = 0; i < 8; i++)
+ _hcd->frame_usecs[i] = max_uframe_usecs[i];
}
- return 0;
}
static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
int ret;
ret = -1;
- if (_qh->speed == USB_SPEED_HIGH) {
- /* if this is a hs transaction we need a full frame */
+ if (_qh->speed == USB_SPEED_HIGH ||
+ _hcd->flags.b.port_speed == DWC_HPRT0_PRTSPD_FULL_SPEED) {
+ /* if this is a hs transaction we need a full frame - or account for FS usecs */
ret = find_single_uframe(_hcd, _qh);
} else {
/* if this is a fs transaction we may need a sequence of frames */
if (status) {
DWC_INFO("%s: Insufficient periodic bandwidth for "
"periodic transfer.\n", __func__);
- return status;
+ return -DWC_E_NO_SPACE;
}
status = check_max_xfer_size(hcd, qh);
if (status) {