dwc_otg_hcd.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
00003  * $Revision: #87 $
00004  * $Date: 2009/04/23 $
00005  * $Change: 1239143 $
00006  *
00007  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
00008  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
00009  * otherwise expressly agreed to in writing between Synopsys and you.
00010  *
00011  * The Software IS NOT an item of Licensed Software or Licensed Product under
00012  * any End User Software License Agreement or Agreement for Licensed Product
00013  * with Synopsys or any supplement thereto. You are permitted to use and
00014  * redistribute this Software in source and binary forms, with or without
00015  * modification, provided that redistributions of source code must retain this
00016  * notice. You may not view, use, disclose, copy or distribute this file or
00017  * any information contained herein except pursuant to this license grant from
00018  * Synopsys. If you do not agree with this notice, including the disclaimer
00019  * below, then you are not authorized to use the Software.
00020  *
00021  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
00022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
00025  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00027  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00031  * DAMAGE.
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                          /* DEBUG */
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 /* 10 secs */ );
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                  * Reset the port.  During a HNP mode switch the reset
00234                  * needs to occur within 1ms and have a duration of at
00235                  * least 50ms.
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          * Set status flags for the hub driver.
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          * Shutdown any transfers in process by clearing the Tx FIFO Empty
00266          * interrupt mask and status bits and disabling subsequent host
00267          * channel interrupts.
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          * Turn off the vbus power only if the core has transitioned to device
00282          * mode. If still in host mode, need to keep power on to detect a
00283          * reconnection.
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         /* Respond with an error status to all URBs in the schedule. */
00298         kill_all_urbs(dwc_otg_hcd);
00299 
00300         if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
00301                 /* Clean up any host channels that were in use. */
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                         /* Flush out any channel requests in slave mode. */
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                                         /* Halt the channel. */
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                                  * Added for Descriptor DMA to prevent channel double cleanup 
00353                                  * in release_channel_ddma(). Which called from ep_disable
00354                                  * when device disconnect.
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          * The root hub should be disconnected before this function is called.
00430          * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
00431          * and the QH lists (via ..._hcd_endpoint_disable).
00432          */
00433 
00434         /* Turn off all host-specific interrupts. */
00435         dwc_otg_disable_host_interrupts(hcd->core_if);
00436 
00437         /* Turn off the vbus power */
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                 /* No longer connected. */
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                         /* Do not schedule SG transcations until qtd has URB_GIVEBACK_ASAP set */
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                 /* The QTD is in process (it has been assigned to a channel). */
00510                 if (hcd->flags.b.port_connect_status) {
00511                         /*
00512                          * If still connected (i.e. in host mode), halt the
00513                          * channel so it can be used for other transfers. If
00514                          * no longer connected, the host registers can't be
00515                          * written to halt the channel since the core is in
00516                          * device mode.
00517                          */
00518                         dwc_otg_hc_halt(hcd->core_if, qh->channel,
00519                                         DWC_OTG_HC_XFER_URB_DEQUEUE);
00520                 }
00521         }
00522 
00523         /*
00524          * Free the QTD and clean up the associated QH. Leave the QH in the
00525          * schedule if it has any remaining QTDs.
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          * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove 
00577          * and qh_free to prevent stack dump on dwc_dma_free() with 
00578          * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() 
00579          * and dwc_otg_hcd_frame_list_alloc().
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                 /* The list hasn't been initialized yet. */
00630                 return;
00631         }
00632 
00633         /* Ensure there are no QTDs or URBs left. */
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         /* Free memory for QH/QTD lists */
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         /* Free memory for the host channels. */
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         /* Register the HCD CIL Callbacks */
00704         dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
00705                                            &hcd_cil_callbacks, hcd);
00706 
00707         /* Initialize the non-periodic schedule. */
00708         DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
00709         DWC_LIST_INIT(&hcd->non_periodic_sched_active);
00710 
00711         /* Initialize the periodic schedule. */
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          * Create a host channel descriptor for each host channel implemented
00719          * in the controller. Initialize the channel descriptor array.
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         /* Initialize the Connection timeout timer. */
00745         hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
00746                                           dwc_otg_hcd_connect_timeout, 0);
00747 
00748         /* Initialize reset tasklet. */
00749         hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd);
00750 
00751         /*
00752          * Allocate space for storing data on status transactions. Normally no
00753          * data is sent, but this space acts as a bit bucket. This must be
00754          * done after usb_add_hcd since that function allocates the DMA buffer
00755          * pool.
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         /* Turn off all host-specific interrupts. */
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          * Put all channels in the free channel list and clean up channel
00804          * states.
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         /* Initialize the DWC core for host mode operation. */
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         /* Remove the host channel from the free list. */
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          * Use usb_pipedevice to determine device address. This address is
00855          * 0 before the SET_ADDRESS command and the correct address afterward.
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          * The following values may be modified in the transfer type section
00871          * below. The xfer_len value may be reduced when the transfer is
00872          * started to accommodate the max widths of the XferSize and PktCnt
00873          * fields in the HCTSIZn register.
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                 /* For non-dword aligned case */
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          * Set the split attributes
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                          * Direction is opposite of data direction or IN if no
00931                          * data.
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                         /* For non-dword aligned buffers */
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         /* non DWORD-aligned buffer case */     
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                  * This value may be modified when the transfer is started to
01033                  * reflect the actual transfer length.
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         /* Process entries in the periodic ready list. */
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                  * Move the QH from the periodic ready schedule to the
01077                  * periodic assigned schedule.
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          * Process entries in the inactive portion of the non-periodic
01088          * schedule. Some free host channels may not be used if they are
01089          * reserved for periodic transfers.
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                  * Move the QH from the non-periodic inactive schedule to the
01104                  * non-periodic active schedule.
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                 /* Don't queue a request if the channel has been halted. */
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                  * Set a flag if we're queuing high-bandwidth in slave mode.
01233                  * The flag prevents any halts to get into the request queue in
01234                  * the middle of multiple high-bandwidth packets getting queued.
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                  * In Slave mode, stay on the current transfer until there is
01249                  * nothing more to do or the high-bandwidth request count is
01250                  * reached. In DMA mode, only need to queue one request. The
01251                  * controller automatically handles multiple packets for
01252                  * high-bandwidth transfers.
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                          * Move the QH from the periodic assigned schedule to
01259                          * the periodic queued schedule.
01260                          */
01261                         DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
01262                                            &qh->qh_list_entry);
01263 
01264                         /* done queuing high bandwidth */
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                          * May need to queue more transactions as the request
01288                          * queue or Tx FIFO empties. Enable the periodic Tx
01289                          * FIFO empty interrupt. (Always use the half-empty
01290                          * level to ensure that new requests are loaded as
01291                          * soon as possible.)
01292                          */
01293                         dwc_modify_reg32(&global_regs->gintmsk, 0,
01294                                          intr_mask.d32);
01295                 } else {
01296                         /*
01297                          * Disable the Tx FIFO empty interrupt since there are
01298                          * no more transactions that need to be queued right
01299                          * now. This function is called from interrupt
01300                          * handlers to queue more transactions as transfer
01301                          * states change.
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          * Keep track of the starting point. Skip over the start-of-list
01340          * entry.
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          * Process once through the active list or until no more space is
01349          * available in the request queue or the Tx FIFO.
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                 /* Advance to next QH, skipping start-of-list entry. */
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                          * May need to queue more transactions as the request
01396                          * queue or Tx FIFO empties. Enable the non-periodic
01397                          * Tx FIFO empty interrupt. (Always use the half-empty
01398                          * level to ensure that new requests are loaded as
01399                          * soon as possible.)
01400                          */
01401                         dwc_modify_reg32(&global_regs->gintmsk, 0,
01402                                          intr_mask.d32);
01403                 } else {
01404                         /*
01405                          * Disable the Tx FIFO empty interrupt since there are
01406                          * no more transactions that need to be queued right
01407                          * now. This function is called from interrupt
01408                          * handlers to queue more transactions as transfer
01409                          * states change.
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         /* Process host channels associated with periodic transfers. */
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         /* Process host channels associated with non-periodic transfers. */
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                          * Ensure NP Tx FIFO empty interrupt is disabled when
01448                          * there are no non-periodic transfers to process.
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  * Quick and dirty hack to implement the HS Electrical Test
01461  * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
01462  *
01463  * This code was copied from our userspace app "hset". It sends a
01464  * Get Device Descriptor control sequence in two parts, first the
01465  * Setup packet by itself, followed some time later by the In and
01466  * Ack packets. Rather than trying to figure out how to add this
01467  * functionality to the normal driver code, we just hijack the
01468  * hardware, using these two function to drive the hardware
01469  * directly.
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         /* Enable HAINTs */
01486         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);
01487 
01488         /* Enable HCINTs */
01489         dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);
01490 
01491         /* Read GINTSTS */
01492         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01493 
01494         /* Read HAINT */
01495         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01496 
01497         /* Read HCINT */
01498         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01499 
01500         /* Read HCCHAR */
01501         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01502 
01503         /* Clear HCINT */
01504         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01505 
01506         /* Clear HAINT */
01507         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01508 
01509         /* Clear GINTSTS */
01510         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01511 
01512         /* Read GINTSTS */
01513         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01514 
01515         /*
01516          * Send Setup packet (Get Device Descriptor)
01517          */
01518 
01519         /* Make sure channel is disabled */
01520         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01521         if (hcchar.b.chen) {
01522                 hcchar.b.chdis = 1;
01523 //              hcchar.b.chen = 1;
01524                 dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
01525                 //sleep(1);
01526                 dwc_mdelay(1000);
01527 
01528                 /* Read GINTSTS */
01529                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01530 
01531                 /* Read HAINT */
01532                 haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01533 
01534                 /* Read HCINT */
01535                 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01536 
01537                 /* Read HCCHAR */
01538                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01539 
01540                 /* Clear HCINT */
01541                 dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01542 
01543                 /* Clear HAINT */
01544                 dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01545 
01546                 /* Clear GINTSTS */
01547                 dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01548 
01549                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01550         }
01551 
01552         /* Set HCTSIZ */
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         /* Set HCCHAR */
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         /* Fill FIFO with Setup data for Get Device Descriptor */
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         /* Wait for host channel interrupt */
01576         do {
01577                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01578         } while (gintsts.b.hcintr == 0);
01579 
01580 
01581         /* Disable HCINTs */
01582         dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);
01583 
01584         /* Disable HAINTs */
01585         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);
01586 
01587         /* Read HAINT */
01588         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01589 
01590         /* Read HCINT */
01591         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01592 
01593         /* Read HCCHAR */
01594         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01595 
01596         /* Clear HCINT */
01597         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01598 
01599         /* Clear HAINT */
01600         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01601 
01602         /* Clear GINTSTS */
01603         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01604 
01605         /* Read GINTSTS */
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         /* Enable HAINTs */
01619         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);
01620 
01621         /* Enable HCINTs */
01622         dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);
01623 
01624         /* Read GINTSTS */
01625         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01626 
01627         /* Read HAINT */
01628         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01629 
01630         /* Read HCINT */
01631         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01632 
01633         /* Read HCCHAR */
01634         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01635 
01636         /* Clear HCINT */
01637         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01638 
01639         /* Clear HAINT */
01640         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01641 
01642         /* Clear GINTSTS */
01643         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01644 
01645         /* Read GINTSTS */
01646         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01647 
01648         /*
01649          * Receive Control In packet
01650          */
01651 
01652         /* Make sure channel is disabled */
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                 //sleep(1);
01659                 dwc_mdelay(1000);
01660 
01661                 /* Read GINTSTS */
01662                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01663 
01664                 /* Read HAINT */
01665                 haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01666 
01667                 /* Read HCINT */
01668                 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01669 
01670                 /* Read HCCHAR */
01671                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01672 
01673                 /* Clear HCINT */
01674                 dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01675 
01676                 /* Clear HAINT */
01677                 dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01678 
01679                 /* Clear GINTSTS */
01680                 dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01681 
01682                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01683         }
01684 
01685         /* Set HCTSIZ */
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         /* Set HCCHAR */
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         /* Wait for receive status queue interrupt */
01704         do {
01705                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01706         } while (gintsts.b.rxstsqlvl == 0);
01707 
01708 
01709         /* Read RXSTS */
01710         grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp);
01711 
01712         /* Clear RXSTSQLVL in GINTSTS */
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                 /* Read the data into the host buffer */
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         /* Wait for receive status queue interrupt */
01739         do {
01740                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01741         } while (gintsts.b.rxstsqlvl == 0);
01742 
01743 
01744         /* Read RXSTS */
01745         grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp);
01746 
01747         /* Clear RXSTSQLVL in GINTSTS */
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         /* Wait for host channel interrupt */
01763         do {
01764                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01765         } while (gintsts.b.hcintr == 0);
01766 
01767 
01768         /* Read HAINT */
01769         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01770 
01771         /* Read HCINT */
01772         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01773 
01774         /* Read HCCHAR */
01775         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01776 
01777         /* Clear HCINT */
01778         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01779 
01780         /* Clear HAINT */
01781         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01782 
01783         /* Clear GINTSTS */
01784         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01785 
01786         /* Read GINTSTS */
01787         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01788 
01789 //      usleep(100000);
01790 //      mdelay(100);
01791         dwc_mdelay(1);
01792 
01793         /*
01794          * Send handshake packet
01795          */
01796 
01797         /* Read HAINT */
01798         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01799 
01800         /* Read HCINT */
01801         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01802 
01803         /* Read HCCHAR */
01804         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01805 
01806         /* Clear HCINT */
01807         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01808 
01809         /* Clear HAINT */
01810         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01811 
01812         /* Clear GINTSTS */
01813         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01814 
01815         /* Read GINTSTS */
01816         gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01817 
01818         /* Make sure channel is disabled */
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                 //sleep(1);
01825                 dwc_mdelay(1000);
01826 
01827                 /* Read GINTSTS */
01828                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01829 
01830                 /* Read HAINT */
01831                 haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01832 
01833                 /* Read HCINT */
01834                 hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01835 
01836                 /* Read HCCHAR */
01837                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01838 
01839                 /* Clear HCINT */
01840                 dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01841 
01842                 /* Clear HAINT */
01843                 dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01844 
01845                 /* Clear GINTSTS */
01846                 dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01847 
01848                 hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01849         }
01850 
01851         /* Set HCTSIZ */
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         /* Set HCCHAR */
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         /* Wait for host channel interrupt */
01870         do {
01871                 gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
01872         } while (gintsts.b.hcintr == 0);
01873 
01874 
01875         /* Disable HCINTs */
01876         dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);
01877 
01878         /* Disable HAINTs */
01879         dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);
01880 
01881         /* Read HAINT */
01882         haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
01883 
01884         /* Read HCINT */
01885         hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
01886 
01887         /* Read HCCHAR */
01888         hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
01889 
01890         /* Clear HCINT */
01891         dwc_write_reg32(&hc_regs->hcint, hcint.d32);
01892 
01893         /* Clear HAINT */
01894         dwc_write_reg32(&hc_global_regs->haint, haint.d32);
01895 
01896         /* Clear GINTSTS */
01897         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
01898 
01899         /* Read GINTSTS */
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                         /* Nothing required here */
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                         /* Clear Resume bit */
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                                 /* Clear Enbl_L1Gating bit. */
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                                 /* This bit will be cleared in wakeup interrupt handle */
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                         /* Port inidicator not supported */
02006                         break;
02007                 case UHF_C_PORT_CONNECTION:
02008                         /* Clears drivers internal connect status change
02009                          * flag */
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                         /* Clears the driver's internal Port Reset Change
02016                          * flag */
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                         /* Clears the driver's internal Port
02023                          * Enable/Disable Change flag */
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                         /* Clears the driver's internal Port Suspend
02030                          * Change flag, which is set when resume signaling on
02031                          * the host port is complete */
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                          * The port is disconnected, which means the core is
02103                          * either in device mode or it soon will be. Just
02104                          * return 0's for the remainder of the port status
02105                          * since the port register can't be read if the core
02106                          * is in device mode.
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                 /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
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                 /* No HUB features supported */
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                          * The port is disconnected, which means the core is
02161                          * either in device mode or it soon will be. Just
02162                          * return without doing anything since the port
02163                          * register can't be written if the core is in device
02164                          * mode.
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                                 /* Update lx_state */
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                         /* Suspend the Phy Clock */
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                         /* For HNP the bus must be suspended for at least 200ms. */
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                         /* When B-Host the Port reset bit is set in
02240                          * the Start HCD Callback function, so that
02241                          * the reset is started within 1ms of the HNP
02242                          * success interrupt. */
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                         /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
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; /* Now back to the on state */
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);      /* MSB wIndex USB */
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                                         /* Setup global vars with reg addresses (quick and
02273                                          * dirty hack, should be cleaned up)
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) {   /* HS_HOST_PORT_SUSPEND_RESUME */
02287                                                 /* Save current interrupt mask */
02288                                                 gintmsk.d32 =
02289                                                     dwc_read_reg32
02290                                                     (&global_regs->gintmsk);
02291 
02292                                                 /* Disable all interrupts while we muck with
02293                                                  * the hardware directly
02294                                                  */
02295                                                 dwc_write_reg32(&global_regs->
02296                                                                 gintmsk, 0);
02297 
02298                                                 /* 15 second delay per the test spec */
02299                                                 dwc_mdelay(15000);
02300 
02301                                                 /* Drive suspend on the root port */
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                                                 /* 15 second delay per the test spec */
02311                                                 dwc_mdelay(15000);
02312 
02313                                                 /* Drive resume on the root port */
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                                                 /* Clear the resume bit */
02324                                                 hprt0.b.prtres = 0;
02325                                                 dwc_write_reg32(core_if->
02326                                                                 host_if->hprt0,
02327                                                                 hprt0.d32);
02328 
02329                                                 /* Restore interrupts */
02330                                                 dwc_write_reg32(&global_regs->
02331                                                                 gintmsk,
02332                                                                 gintmsk.d32);
02333                                         } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
02334                                                 /* Save current interrupt mask */
02335                                                 gintmsk.d32 =
02336                                                     dwc_read_reg32
02337                                                     (&global_regs->gintmsk);
02338 
02339                                                 /* Disable all interrupts while we muck with
02340                                                  * the hardware directly
02341                                                  */
02342                                                 dwc_write_reg32(&global_regs->
02343                                                                 gintmsk, 0);
02344 
02345                                                 /* 15 second delay per the test spec */
02346                                                 dwc_mdelay(15000);
02347 
02348                                                 /* Send the Setup packet */
02349                                                 do_setup();
02350 
02351                                                 /* 15 second delay so nothing else happens for awhile */
02352                                                 dwc_mdelay(15000);
02353 
02354                                                 /* Restore interrupts */
02355                                                 dwc_write_reg32(&global_regs->
02356                                                                 gintmsk,
02357                                                                 gintmsk.d32);
02358                                         } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
02359                                                 /* Save current interrupt mask */
02360                                                 gintmsk.d32 =
02361                                                     dwc_read_reg32
02362                                                     (&global_regs->gintmsk);
02363 
02364                                                 /* Disable all interrupts while we muck with
02365                                                  * the hardware directly
02366                                                  */
02367                                                 dwc_write_reg32(&global_regs->
02368                                                                 gintmsk, 0);
02369 
02370                                                 /* Send the Setup packet */
02371                                                 do_setup();
02372 
02373                                                 /* 15 second delay so nothing else happens for awhile */
02374                                                 dwc_mdelay(15000);
02375 
02376                                                 /* Send the In and Ack packets */
02377                                                 do_in_ack();
02378 
02379                                                 /* 15 second delay so nothing else happens for awhile */
02380                                                 dwc_mdelay(15000);
02381 
02382                                                 /* Restore interrupts */
02383                                                 dwc_write_reg32(&global_regs->
02384                                                                 gintmsk,
02385                                                                 gintmsk.d32);
02386                                         }
02387                                 }
02388                                 break;
02389                         }
02390 #endif                          /* DWC_HS_ELECT_TST */
02391 
02392                 case UHF_PORT_INDICATOR:
02393                         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
02394                                     "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
02395                         /* Not supported */
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                         /* Check if the port currently is in SLEEP state */
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;     /* Return success */
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                         /* Disable LPM interrupt */
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                         /* We will consider timeout if time_usecs microseconds pass,
02462                          * and we don't receive LPM transaction status.
02463                          * After receiving non-error responce(ACK/NYET/STALL) from device,
02464                          *  core will set lpmtranrcvd bit.
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                         /* lpm_int bit will be cleared in LPM interrupt handler */
02476 
02477                         /* Now fill status
02478                          * 0x00 - Success
02479                          * 0x10 - NYET
02480                          * 0x11 - Timeout
02481                          */
02482                         if (!gintsts.b.lpmtranrcvd) {
02483                                 buf[0] = 0x3;   /* Completion code is Timeout */
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                                         /* ACK responce from the device */
02491                                         buf[0] = 0x00;  /* Success */
02492                                 } else if (lpmcfg.b.lpm_resp == 0x2) {
02493                                         /* NYET responce from the device */
02494                                         buf[0] = 0x2;
02495                                 } else {
02496                                         /* Otherwise responce with Timeout */
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                          /* CONFIG_USB_DWC_OTG_LPM */
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         /* Mask host channel interrupts. */
02537         gintmsk.b.hcintr = 1;
02538         dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
02539 
02540         /* Fill fields that core needs for LPM transaction */
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;     /* OUT */
02547         dwc_write_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
02548                         hcchar.d32);
02549 
02550         /* Remove the host channel from the free list. */
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         /* Return host channel to free list */
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         /* Read LPM config register */
02591         lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg);
02592 
02593         /* Program LPM transaction fields */
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         /* Program LPM config register */
02600         dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
02601 
02602         /* Send LPM transaction */
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                          /* CONFIG_USB_DWC_OTG_LPM */
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                          /* DWC_DEVICE_ONLY */

Generated on Tue May 5 02:22:48 2009 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.4.7