dwc_otg_hcd_intr.c

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