Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

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

Generated on Thu Oct 27 03:56:37 2011 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.3.9.1