dwc_otg_pcd_intr.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
00003  * $Revision: #93 $
00004  * $Date: 2009/04/02 $
00005  * $Change: 1224216 $
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_HOST_ONLY
00034 
00035 #include "dwc_otg_pcd.h"
00036 
00037 #ifdef DWC_UTE_CFI
00038 #include "dwc_otg_cfi.h"
00039 #endif
00040 
00041 //#define PRINT_CFI_DMA_DESCS
00042 
00043 #define DEBUG_EP0
00044 
00048 static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
00049 {
00050 
00051         if (reset) {
00052                 pcd->b_hnp_enable = 0;
00053                 pcd->a_hnp_support = 0;
00054                 pcd->a_alt_hnp_support = 0;
00055         }
00056 
00057         if (pcd->fops->hnp_changed) {
00058                 pcd->fops->hnp_changed(pcd);
00059         }
00060 }
00061 
00076 static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
00077 {
00078 #ifdef DEBUG
00079         char str[40];
00080 
00081         switch (pcd->ep0state) {
00082         case EP0_DISCONNECT:
00083                 dwc_strcpy(str, "EP0_DISCONNECT");
00084                 break;
00085         case EP0_IDLE:
00086                 dwc_strcpy(str, "EP0_IDLE");
00087                 break;
00088         case EP0_IN_DATA_PHASE:
00089                 dwc_strcpy(str, "EP0_IN_DATA_PHASE");
00090                 break;
00091         case EP0_OUT_DATA_PHASE:
00092                 dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
00093                 break;
00094         case EP0_IN_STATUS_PHASE:
00095                 dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
00096                 break;
00097         case EP0_OUT_STATUS_PHASE:
00098                 dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
00099                 break;
00100         case EP0_STALL:
00101                 dwc_strcpy(str, "EP0_STALL");
00102                 break;
00103         default:
00104                 dwc_strcpy(str, "EP0_INVALID");
00105         }
00106 
00107         DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
00108 #endif
00109 }
00110 
00111 #ifdef DWC_UTE_CFI
00112 static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
00113                               const uint8_t * epname, int descnum)
00114 {
00115         CFI_INFO
00116             ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
00117              epname, descnum, ddesc->buf, ddesc->status.b.bytes,
00118              ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
00119              ddesc->status.b.bs);
00120 }
00121 #endif
00122 
00126 static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
00127 {
00128         int i;
00129         int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
00130         if (ep_num == 0) {
00131                 return &pcd->ep0;
00132         } else {
00133                 for (i = 0; i < num_in_eps; ++i) {
00134                         if (pcd->in_ep[i].dwc_ep.num == ep_num)
00135                                 return &pcd->in_ep[i];
00136                 }
00137                 return 0;
00138         }
00139 }
00140 
00144 static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
00145 {
00146         int i;
00147         int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
00148         if (ep_num == 0) {
00149                 return &pcd->ep0;
00150         } else {
00151                 for (i = 0; i < num_out_eps; ++i) {
00152                         if (pcd->out_ep[i].dwc_ep.num == ep_num)
00153                                 return &pcd->out_ep[i];
00154                 }
00155                 return 0;
00156         }
00157 }
00158 
00163 dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
00164 {
00165         dwc_otg_pcd_ep_t *ep;
00166         uint32_t ep_num = UE_GET_ADDR(wIndex);
00167 
00168         if (ep_num == 0) {
00169                 ep = &pcd->ep0;
00170         } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {   /* in ep */
00171                 ep = &pcd->in_ep[ep_num - 1];
00172         } else {
00173                 ep = &pcd->out_ep[ep_num - 1];
00174         }
00175 
00176         return ep;
00177 }
00178 
00183 void start_next_request(dwc_otg_pcd_ep_t * ep)
00184 {
00185         dwc_otg_pcd_request_t *req = 0;
00186         uint32_t max_transfer =
00187             GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
00188 
00189 #ifdef DWC_UTE_CFI
00190         struct dwc_otg_pcd *pcd;
00191         pcd = ep->pcd;
00192 #endif
00193 
00194         if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
00195                 req = DWC_CIRCLEQ_FIRST(&ep->queue);
00196 
00197 #ifdef DWC_UTE_CFI
00198                 if (ep->dwc_ep.buff_mode != BM_STANDARD) {
00199                         ep->dwc_ep.cfi_req_len = req->length;
00200                         pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
00201                 } else {
00202 #endif
00203                 /* Setup and start the Transfer */
00204                 ep->dwc_ep.dma_addr = req->dma;
00205                 ep->dwc_ep.start_xfer_buff = req->buf;
00206                 ep->dwc_ep.xfer_buff = req->buf;
00207                 ep->dwc_ep.sent_zlp = 0;
00208                 ep->dwc_ep.total_len = req->length;
00209                 ep->dwc_ep.xfer_len = 0;
00210                 ep->dwc_ep.xfer_count = 0;
00211 
00212                 ep->dwc_ep.maxxfer = max_transfer;
00213                 if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
00214                         uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
00215                             - (DDMA_MAX_TRANSFER_SIZE % 4);
00216                         if (ep->dwc_ep.is_in) {
00217                                         if (ep->dwc_ep.maxxfer >
00218                                             DDMA_MAX_TRANSFER_SIZE) {
00219                                         ep->dwc_ep.maxxfer =
00220                                             DDMA_MAX_TRANSFER_SIZE;
00221                                 }
00222                         } else {
00223                                 if (ep->dwc_ep.maxxfer > out_max_xfer) {
00224                                                 ep->dwc_ep.maxxfer =
00225                                                     out_max_xfer;
00226                                 }
00227                         }
00228                 }
00229                 if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
00230                         ep->dwc_ep.maxxfer -=
00231                             (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
00232                 }
00233                 if (req->sent_zlp) {
00234                                 if ((ep->dwc_ep.total_len %
00235                                      ep->dwc_ep.maxpacket == 0)
00236                                     && (ep->dwc_ep.total_len != 0)) {
00237                                 ep->dwc_ep.sent_zlp = 1;
00238                         }
00239 
00240                 }
00241 #ifdef DWC_UTE_CFI
00242                 }
00243 #endif
00244                 dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
00245         }
00246 }
00247 
00252 int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
00253 {
00254         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00255 
00256         gintsts_data_t gintsts;
00257 
00258         DWC_DEBUGPL(DBG_PCD, "SOF\n");
00259 
00260         /* Clear interrupt */
00261         gintsts.d32 = 0;
00262         gintsts.b.sofintr = 1;
00263         dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
00264 
00265         return 1;
00266 }
00267 
00285 int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
00286 {
00287         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00288         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
00289         gintmsk_data_t gintmask = {.d32 = 0 };
00290         device_grxsts_data_t status;
00291         dwc_otg_pcd_ep_t *ep;
00292         gintsts_data_t gintsts;
00293 #ifdef DEBUG
00294         static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
00295 #endif
00296 
00297         //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
00298         /* Disable the Rx Status Queue Level interrupt */
00299         gintmask.b.rxstsqlvl = 1;
00300         dwc_modify_reg32(&global_regs->gintmsk, gintmask.d32, 0);
00301 
00302         /* Get the Status from the top of the FIFO */
00303         status.d32 = dwc_read_reg32(&global_regs->grxstsp);
00304 
00305         DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
00306                     "pktsts:%x Frame:%d(0x%0x)\n",
00307                     status.b.epnum, status.b.bcnt,
00308                     dpid_str[status.b.dpid],
00309                     status.b.pktsts, status.b.fn, status.b.fn);
00310         /* Get pointer to EP structure */
00311         ep = get_out_ep(pcd, status.b.epnum);
00312 
00313         switch (status.b.pktsts) {
00314         case DWC_DSTS_GOUT_NAK:
00315                 DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
00316                 break;
00317         case DWC_STS_DATA_UPDT:
00318                 DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
00319                 if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
00321                         dwc_otg_read_packet(core_if,
00322                                             ep->dwc_ep.xfer_buff,
00323                                             status.b.bcnt);
00324                         ep->dwc_ep.xfer_count += status.b.bcnt;
00325                         ep->dwc_ep.xfer_buff += status.b.bcnt;
00326                 }
00327                 break;
00328         case DWC_STS_XFER_COMP:
00329                 DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
00330                 break;
00331         case DWC_DSTS_SETUP_COMP:
00332 #ifdef DEBUG_EP0
00333                 DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
00334 #endif
00335                 break;
00336         case DWC_DSTS_SETUP_UPDT:
00337                 dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
00338 #ifdef DEBUG_EP0
00339                 DWC_DEBUGPL(DBG_PCD,
00340                             "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
00341                             pcd->setup_pkt->req.bmRequestType,
00342                             pcd->setup_pkt->req.bRequest,
00343                             UGETW(pcd->setup_pkt->req.wValue),
00344                             UGETW(pcd->setup_pkt->req.wIndex),
00345                             UGETW(pcd->setup_pkt->req.wLength));
00346 #endif
00347                 ep->dwc_ep.xfer_count += status.b.bcnt;
00348                 break;
00349         default:
00350                 DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
00351                             status.b.pktsts);
00352                 break;
00353         }
00354 
00355         /* Enable the Rx Status Queue Level interrupt */
00356         dwc_modify_reg32(&global_regs->gintmsk, 0, gintmask.d32);
00357         /* Clear interrupt */
00358         gintsts.d32 = 0;
00359         gintsts.b.rxstsqlvl = 1;
00360         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
00361 
00362         //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
00363         return 1;
00364 }
00365 
00378 static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
00379 {
00380         dwc_otg_device_global_regs_t *dev_global_regs =
00381             core_if->dev_if->dev_global_regs;
00382         const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
00383         /* Number of Token Queue Registers */
00384         const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
00385         dtknq1_data_t dtknqr1;
00386         uint32_t in_tkn_epnums[4];
00387         int ndx = 0;
00388         int i = 0;
00389         volatile uint32_t *addr = &dev_global_regs->dtknqr1;
00390         int epnum = 0;
00391 
00392         //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
00393 
00394         /* Read the DTKNQ Registers */
00395         for (i = 0; i < DTKNQ_REG_CNT; i++) {
00396                 in_tkn_epnums[i] = dwc_read_reg32(addr);
00397                 DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
00398                             in_tkn_epnums[i]);
00399                 if (addr == &dev_global_regs->dvbusdis) {
00400                         addr = &dev_global_regs->dtknqr3_dthrctl;
00401                 } else {
00402                         ++addr;
00403                 }
00404 
00405         }
00406 
00407         /* Copy the DTKNQR1 data to the bit field. */
00408         dtknqr1.d32 = in_tkn_epnums[0];
00409         /* Get the EP numbers */
00410         in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
00411         ndx = dtknqr1.b.intknwptr - 1;
00412 
00413         //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
00414         if (ndx == -1) {
00417                 int cnt = TOKEN_Q_DEPTH;
00418                 if (TOKEN_Q_DEPTH <= 6) {
00419                         cnt = TOKEN_Q_DEPTH - 1;
00420                 } else if (TOKEN_Q_DEPTH <= 14) {
00421                         cnt = TOKEN_Q_DEPTH - 7;
00422                 } else if (TOKEN_Q_DEPTH <= 22) {
00423                         cnt = TOKEN_Q_DEPTH - 15;
00424                 } else {
00425                         cnt = TOKEN_Q_DEPTH - 23;
00426                 }
00427                 epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
00428         } else {
00429                 if (ndx <= 5) {
00430                         epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
00431                 } else if (ndx <= 13) {
00432                         ndx -= 6;
00433                         epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
00434                 } else if (ndx <= 21) {
00435                         ndx -= 14;
00436                         epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
00437                 } else if (ndx <= 29) {
00438                         ndx -= 22;
00439                         epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
00440                 }
00441         }
00442         //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
00443         return epnum;
00444 }
00445 
00451 int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
00452 {
00453         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00454         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
00455         dwc_otg_dev_in_ep_regs_t *ep_regs;
00456         gnptxsts_data_t txstatus = {.d32 = 0 };
00457         gintsts_data_t gintsts;
00458 
00459         int epnum = 0;
00460         dwc_otg_pcd_ep_t *ep = 0;
00461         uint32_t len = 0;
00462         int dwords;
00463 
00464         /* Get the epnum from the IN Token Learning Queue. */
00465         epnum = get_ep_of_last_in_token(core_if);
00466         ep = get_in_ep(pcd, epnum);
00467 
00468         DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
00469 
00470         ep_regs = core_if->dev_if->in_ep_regs[epnum];
00471 
00472         len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
00473         if (len > ep->dwc_ep.maxpacket) {
00474                 len = ep->dwc_ep.maxpacket;
00475         }
00476         dwords = (len + 3) / 4;
00477 
00478         /* While there is space in the queue and space in the FIFO and
00479          * More data to tranfer, Write packets to the Tx FIFO */
00480         txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts);
00481         DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
00482 
00483         while (txstatus.b.nptxqspcavail > 0 &&
00484                txstatus.b.nptxfspcavail > dwords &&
00485                ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
00486                 /* Write the FIFO */
00487                 dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
00488                 len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
00489 
00490                 if (len > ep->dwc_ep.maxpacket) {
00491                         len = ep->dwc_ep.maxpacket;
00492                 }
00493 
00494                 dwords = (len + 3) / 4;
00495                 txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts);
00496                 DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
00497         }
00498 
00499         DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
00500                     dwc_read_reg32(&global_regs->gnptxsts));
00501 
00502         /* Clear interrupt */
00503         gintsts.d32 = 0;
00504         gintsts.b.nptxfempty = 1;
00505         dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
00506 
00507         return 1;
00508 }
00509 
00515 static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
00516 {
00517         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00518         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
00519         dwc_otg_dev_in_ep_regs_t *ep_regs;
00520         dtxfsts_data_t txstatus = {.d32 = 0 };
00521         dwc_otg_pcd_ep_t *ep = 0;
00522         uint32_t len = 0;
00523         int dwords;
00524 
00525         ep = get_in_ep(pcd, epnum);
00526 
00527         DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
00528 
00529         ep_regs = core_if->dev_if->in_ep_regs[epnum];
00530 
00531         len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
00532 
00533         if (len > ep->dwc_ep.maxpacket) {
00534                 len = ep->dwc_ep.maxpacket;
00535         }
00536 
00537         dwords = (len + 3) / 4;
00538 
00539         /* While there is space in the queue and space in the FIFO and
00540          * More data to tranfer, Write packets to the Tx FIFO */
00541         txstatus.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts);
00542         DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
00543 
00544         while (txstatus.b.txfspcavail > dwords &&
00545                ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
00546                ep->dwc_ep.xfer_len != 0) {
00547                 /* Write the FIFO */
00548                 dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
00549 
00550                 len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
00551                 if (len > ep->dwc_ep.maxpacket) {
00552                         len = ep->dwc_ep.maxpacket;
00553                 }
00554 
00555                 dwords = (len + 3) / 4;
00556                 txstatus.d32 =
00557                     dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts);
00558                 DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
00559                             txstatus.d32);
00560         }
00561 
00562         DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
00563                     dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts));
00564 
00565         return 1;
00566 }
00567 
00573 void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
00574 {
00575         int i, num_in_eps, num_out_eps;
00576         dwc_otg_pcd_ep_t *ep;
00577 
00578         gintmsk_data_t intr_mask = {.d32 = 0 };
00579 
00580         DWC_SPINLOCK(pcd->lock);
00581 
00582         num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
00583         num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
00584 
00585         DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
00586         /* don't disconnect drivers more than once */
00587         if (pcd->ep0state == EP0_DISCONNECT) {
00588                 DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
00589                 return;
00590         }
00591         pcd->ep0state = EP0_DISCONNECT;
00592 
00593         /* Reset the OTG state. */
00594         dwc_otg_pcd_update_otg(pcd, 1);
00595 
00596         /* Disable the NP Tx Fifo Empty Interrupt. */
00597         intr_mask.b.nptxfempty = 1;
00598         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
00599                          intr_mask.d32, 0);
00600 
00601         /* Flush the FIFOs */
00603         dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
00604         dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
00605 
00606         /* prevent new request submissions, kill any outstanding requests  */
00607         ep = &pcd->ep0;
00608         dwc_otg_request_nuke(ep);
00609         /* prevent new request submissions, kill any outstanding requests  */
00610         for (i = 0; i < num_in_eps; i++) {
00611                 dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
00612                 dwc_otg_request_nuke(ep);
00613         }
00614         /* prevent new request submissions, kill any outstanding requests  */
00615         for (i = 0; i < num_out_eps; i++) {
00616                 dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
00617                 dwc_otg_request_nuke(ep);
00618         }
00619 
00620         /* report disconnect; the driver is already quiesced */
00621         if (pcd->fops->disconnect) {
00622                 DWC_SPINUNLOCK(pcd->lock);
00623                 pcd->fops->disconnect(pcd);
00624                 DWC_SPINLOCK(pcd->lock);
00625         }
00626         DWC_SPINUNLOCK(pcd->lock);
00627 }
00628 
00632 int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
00633 {
00634         gintmsk_data_t intr_mask = {.d32 = 0 };
00635         gintsts_data_t gintsts;
00636 
00637         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
00638         intr_mask.b.i2cintr = 1;
00639         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
00640                          intr_mask.d32, 0);
00641 
00642         /* Clear interrupt */
00643         gintsts.d32 = 0;
00644         gintsts.b.i2cintr = 1;
00645         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
00646                         gintsts.d32);
00647         return 1;
00648 }
00649 
00653 int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
00654 {
00655         gintsts_data_t gintsts;
00656 #if defined(VERBOSE)
00657         DWC_PRINTF("Early Suspend Detected\n");
00658 #endif
00659         /* Clear interrupt */
00660         gintsts.d32 = 0;
00661         gintsts.b.erlysuspend = 1;
00662         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
00663                         gintsts.d32);
00664         return 1;
00665 }
00666 
00684 static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
00685                                  dwc_otg_pcd_t * pcd)
00686 {
00687         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
00688         deptsiz0_data_t doeptsize0 = {.d32 = 0 };
00689         dwc_otg_dev_dma_desc_t *dma_desc;
00690         depctl_data_t doepctl = {.d32 = 0 };
00691 
00692 #ifdef VERBOSE
00693         DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
00694                     dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
00695 #endif
00696 
00697         doeptsize0.b.supcnt = 3;
00698         doeptsize0.b.pktcnt = 1;
00699         doeptsize0.b.xfersize = 8 * 3;
00700 
00701         if (core_if->dma_enable) {
00702                 if (!core_if->dma_desc_enable) {
00704                         dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz,
00705                                         doeptsize0.d32);
00706 
00708                         dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma,
00709                                         pcd->setup_pkt_dma_handle);
00710                 } else {
00711                         dev_if->setup_desc_index =
00712                             (dev_if->setup_desc_index + 1) & 1;
00713                         dma_desc =
00714                             dev_if->setup_desc_addr[dev_if->setup_desc_index];
00715 
00717                         dma_desc->status.b.bs = BS_HOST_BUSY;
00718                         dma_desc->status.b.l = 1;
00719                         dma_desc->status.b.ioc = 1;
00720                         dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
00721                         dma_desc->buf = pcd->setup_pkt_dma_handle;
00722                         dma_desc->status.b.bs = BS_HOST_READY;
00723 
00725                         dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma,
00726                                         dev_if->dma_setup_desc_addr[dev_if->
00727                                                                     setup_desc_index]);
00728                 }
00729 
00730         } else {
00732                 dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz,
00733                                 doeptsize0.d32);
00734         }
00735 
00737         doepctl.b.epena = 1;
00738         doepctl.b.cnak = 1;
00739         dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
00740 
00741 #ifdef VERBOSE
00742         DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
00743                     dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
00744         DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
00745                     dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl));
00746 #endif
00747 }
00748 
00772 int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
00773 {
00774         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00775         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
00776         depctl_data_t doepctl = {.d32 = 0 };
00777         daint_data_t daintmsk = {.d32 = 0 };
00778         doepmsk_data_t doepmsk = {.d32 = 0 };
00779         diepmsk_data_t diepmsk = {.d32 = 0 };
00780         dcfg_data_t dcfg = {.d32 = 0 };
00781         grstctl_t resetctl = {.d32 = 0 };
00782         dctl_data_t dctl = {.d32 = 0 };
00783         int i = 0;
00784         gintsts_data_t gintsts;
00785         pcgcctl_data_t power = {.d32 = 0 };
00786 
00787         power.d32 = dwc_read_reg32(core_if->pcgcctl);
00788         if (power.b.stoppclk) {
00789                 power.d32 = 0;
00790                 power.b.stoppclk = 1;
00791                 dwc_modify_reg32(core_if->pcgcctl, power.d32, 0);
00792 
00793                 power.b.pwrclmp = 1;
00794                 dwc_modify_reg32(core_if->pcgcctl, power.d32, 0);
00795 
00796                 power.b.rstpdwnmodule = 1;
00797                 dwc_modify_reg32(core_if->pcgcctl, power.d32, 0);
00798         }
00799 
00800         core_if->lx_state = DWC_OTG_L0;
00801 
00802         DWC_PRINTF("USB RESET\n");
00803 #ifdef DWC_EN_ISOC
00804         for (i = 1; i < 16; ++i) {
00805                 dwc_otg_pcd_ep_t *ep;
00806                 dwc_ep_t *dwc_ep;
00807                 ep = get_in_ep(pcd, i);
00808                 if (ep != 0) {
00809                         dwc_ep = &ep->dwc_ep;
00810                         dwc_ep->next_frame = 0xffffffff;
00811                 }
00812         }
00813 #endif                          /* DWC_EN_ISOC */
00814 
00815         /* reset the HNP settings */
00816         dwc_otg_pcd_update_otg(pcd, 1);
00817 
00818         /* Clear the Remote Wakeup Signalling */
00819         dctl.b.rmtwkupsig = 1;
00820         dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
00821 
00822         /* Set NAK for all OUT EPs */
00823         doepctl.b.snak = 1;
00824         for (i = 0; i <= dev_if->num_out_eps; i++) {
00825                 dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
00826         }
00827 
00828         /* Flush the NP Tx FIFO */
00829         dwc_otg_flush_tx_fifo(core_if, 0x10);
00830         /* Flush the Learning Queue */
00831         resetctl.b.intknqflsh = 1;
00832         dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32);
00833 
00834         if (core_if->multiproc_int_enable) {
00835                 daintmsk.b.inep0 = 1;
00836                 daintmsk.b.outep0 = 1;
00837                 dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk,
00838                                 daintmsk.d32);
00839 
00840                 doepmsk.b.setup = 1;
00841                 doepmsk.b.xfercompl = 1;
00842                 doepmsk.b.ahberr = 1;
00843                 doepmsk.b.epdisabled = 1;
00844 
00845                 if (core_if->dma_desc_enable) {
00846                         doepmsk.b.stsphsercvd = 1;
00847                         doepmsk.b.bna = 1;
00848                 }
00849 /*              
00850                 doepmsk.b.babble = 1;
00851                 doepmsk.b.nyet = 1;
00852                 
00853                 if(core_if->dma_enable) {
00854                         doepmsk.b.nak = 1;
00855                 }
00856 */
00857                 dwc_write_reg32(&dev_if->dev_global_regs->doepeachintmsk[0],
00858                                 doepmsk.d32);
00859 
00860                 diepmsk.b.xfercompl = 1;
00861                 diepmsk.b.timeout = 1;
00862                 diepmsk.b.epdisabled = 1;
00863                 diepmsk.b.ahberr = 1;
00864                 diepmsk.b.intknepmis = 1;
00865 
00866                 if (core_if->dma_desc_enable) {
00867                         diepmsk.b.bna = 1;
00868                 }
00869 /*              
00870                 if(core_if->dma_enable) {
00871                         diepmsk.b.nak = 1;
00872                 }
00873 */
00874                 dwc_write_reg32(&dev_if->dev_global_regs->diepeachintmsk[0],
00875                                 diepmsk.d32);
00876         } else {
00877                 daintmsk.b.inep0 = 1;
00878                 daintmsk.b.outep0 = 1;
00879                 dwc_write_reg32(&dev_if->dev_global_regs->daintmsk,
00880                                 daintmsk.d32);
00881 
00882                 doepmsk.b.setup = 1;
00883                 doepmsk.b.xfercompl = 1;
00884                 doepmsk.b.ahberr = 1;
00885                 doepmsk.b.epdisabled = 1;
00886 
00887                 if (core_if->dma_desc_enable) {
00888                         doepmsk.b.stsphsercvd = 1;
00889                         doepmsk.b.bna = 1;
00890                 }
00891                 dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
00892 
00893                 diepmsk.b.xfercompl = 1;
00894                 diepmsk.b.timeout = 1;
00895                 diepmsk.b.epdisabled = 1;
00896                 diepmsk.b.ahberr = 1;
00897                 diepmsk.b.intknepmis = 1;
00898 
00899                 if (core_if->dma_desc_enable) {
00900                         diepmsk.b.bna = 1;
00901                 }
00902 
00903                 dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
00904         }
00905 
00906         /* Reset Device Address */
00907         dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg);
00908         dcfg.b.devaddr = 0;
00909         dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
00910 
00911         /* setup EP0 to receive SETUP packets */
00912         ep0_out_start(core_if, pcd);
00913 
00914         /* Clear interrupt */
00915         gintsts.d32 = 0;
00916         gintsts.b.usbreset = 1;
00917         dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
00918 
00919         return 1;
00920 }
00921 
00928 static int get_device_speed(dwc_otg_core_if_t * core_if)
00929 {
00930         dsts_data_t dsts;
00931         int speed = 0;
00932         dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
00933 
00934         switch (dsts.b.enumspd) {
00935         case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
00936                 speed = USB_SPEED_HIGH;
00937                 break;
00938         case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
00939         case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
00940                 speed = USB_SPEED_FULL;
00941                 break;
00942 
00943         case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
00944                 speed = USB_SPEED_LOW;
00945                 break;
00946         }
00947 
00948         return speed;
00949 }
00950 
00956 int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
00957 {
00958         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
00959         gintsts_data_t gintsts;
00960         gusbcfg_data_t gusbcfg;
00961         dwc_otg_core_global_regs_t *global_regs =
00962             GET_CORE_IF(pcd)->core_global_regs;
00963         uint8_t utmi16b, utmi8b;
00964         int speed;
00965         DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
00966 
00967         if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
00968                 utmi16b = 6;
00969                 utmi8b = 9;
00970         } else {
00971                 utmi16b = 4;
00972                 utmi8b = 8;
00973         }
00974         dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
00975 
00976 #ifdef DEBUG_EP0
00977         print_ep0_state(pcd);
00978 #endif
00979 
00980         if (pcd->ep0state == EP0_DISCONNECT) {
00981                 pcd->ep0state = EP0_IDLE;
00982         } else if (pcd->ep0state == EP0_STALL) {
00983                 pcd->ep0state = EP0_IDLE;
00984         }
00985 
00986         pcd->ep0state = EP0_IDLE;
00987 
00988         ep0->stopped = 0;
00989 
00990         speed = get_device_speed(GET_CORE_IF(pcd));
00991         pcd->fops->connect(pcd, speed);
00992 
00993         /* Set USB turnaround time based on device speed and PHY interface. */
00994         gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
00995         if (speed == USB_SPEED_HIGH) {
00996                 if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
00997                     DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
00998                         /* ULPI interface */
00999                         gusbcfg.b.usbtrdtim = 9;
01000                 }
01001                 if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
01002                     DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
01003                         /* UTMI+ interface */
01004                         if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
01005                                 gusbcfg.b.usbtrdtim = utmi8b;
01006                         } else if (GET_CORE_IF(pcd)->hwcfg4.b.
01007                                    utmi_phy_data_width == 1) {
01008                                 gusbcfg.b.usbtrdtim = utmi16b;
01009                         } else if (GET_CORE_IF(pcd)->core_params->
01010                                    phy_utmi_width == 8) {
01011                                 gusbcfg.b.usbtrdtim = utmi8b;
01012                         } else {
01013                                 gusbcfg.b.usbtrdtim = utmi16b;
01014                         }
01015                 }
01016                 if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
01017                     DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
01018                         /* UTMI+  OR  ULPI interface */
01019                         if (gusbcfg.b.ulpi_utmi_sel == 1) {
01020                                 /* ULPI interface */
01021                                 gusbcfg.b.usbtrdtim = 9;
01022                         } else {
01023                                 /* UTMI+ interface */
01024                                 if (GET_CORE_IF(pcd)->core_params->
01025                                     phy_utmi_width == 16) {
01026                                         gusbcfg.b.usbtrdtim = utmi16b;
01027                                 } else {
01028                                         gusbcfg.b.usbtrdtim = utmi8b;
01029                                 }
01030                         }
01031                 }
01032         } else {
01033                 /* Full or low speed */
01034                 gusbcfg.b.usbtrdtim = 9;
01035         }
01036         dwc_write_reg32(&global_regs->gusbcfg, gusbcfg.d32);
01037 
01038         /* Clear interrupt */
01039         gintsts.d32 = 0;
01040         gintsts.b.enumdone = 1;
01041         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
01042                         gintsts.d32);
01043         return 1;
01044 }
01045 
01051 int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
01052 {
01053         gintmsk_data_t intr_mask = {.d32 = 0 };
01054         gintsts_data_t gintsts;
01055 
01056         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
01057                    "ISOC Out Dropped");
01058 
01059         intr_mask.b.isooutdrop = 1;
01060         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
01061                          intr_mask.d32, 0);
01062 
01063         /* Clear interrupt */
01064         gintsts.d32 = 0;
01065         gintsts.b.isooutdrop = 1;
01066         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
01067                         gintsts.d32);
01068 
01069         return 1;
01070 }
01071 
01077 int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
01078 {
01079         gintmsk_data_t intr_mask = {.d32 = 0 };
01080         gintsts_data_t gintsts;
01081         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
01082 
01083         intr_mask.b.eopframe = 1;
01084         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
01085                          intr_mask.d32, 0);
01086 
01087         /* Clear interrupt */
01088         gintsts.d32 = 0;
01089         gintsts.b.eopframe = 1;
01090         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
01091                         gintsts.d32);
01092 
01093         return 1;
01094 }
01095 
01105 int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t * core_if)
01106 {
01107         gintsts_data_t gintsts;
01108         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
01109 
01110         /* Clear interrupt */
01111         gintsts.d32 = 0;
01112         gintsts.b.epmismatch = 1;
01113         dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
01114 
01115         return 1;
01116 }
01117 
01121 static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
01122 {
01123         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
01124         usb_device_request_t *ctrl = &pcd->setup_pkt->req;
01125         DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
01126                  ctrl->bmRequestType, ctrl->bRequest, err_val);
01127 
01128         ep0->dwc_ep.is_in = 1;
01129         dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
01130         pcd->ep0.stopped = 1;
01131         pcd->ep0state = EP0_IDLE;
01132         ep0_out_start(GET_CORE_IF(pcd), pcd);
01133 }
01134 
01138 static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
01139                                    usb_device_request_t * ctrl)
01140 {
01141         int ret = 0;
01142         DWC_SPINUNLOCK(pcd->lock);
01143         ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
01144         DWC_SPINLOCK(pcd->lock);
01145         if (ret < 0) {
01146                 ep0_do_stall(pcd, ret);
01147         }
01148 
01161         if (ret == 256 + 999) {
01162                 pcd->request_config = 1;
01163         }
01164 }
01165 
01166 #ifdef DWC_UTE_CFI
01167 
01171 static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
01172                                    struct cfi_usb_ctrlrequest *ctrl_req)
01173 {
01174         int ret = 0;
01175 
01176         if (pcd->fops && pcd->fops->cfi_setup) {
01177                 DWC_SPINUNLOCK(pcd->lock);
01178                 ret = pcd->fops->cfi_setup(pcd, ctrl_req);
01179                 DWC_SPINLOCK(pcd->lock);
01180                 if (ret < 0) {
01181                         ep0_do_stall(pcd, ret);
01182                         return ret;
01183                 }
01184         }
01185 
01186         return ret;
01187 }
01188 #endif
01189 
01194 static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
01195 {
01196         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
01197         if (pcd->ep0state == EP0_STALL) {
01198                 return;
01199         }
01200 
01201         pcd->ep0state = EP0_IN_STATUS_PHASE;
01202 
01203         /* Prepare for more SETUP Packets */
01204         DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
01205         ep0->dwc_ep.xfer_len = 0;
01206         ep0->dwc_ep.xfer_count = 0;
01207         ep0->dwc_ep.is_in = 1;
01208         ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
01209         dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
01210 
01211         /* Prepare for more SETUP Packets */
01212         //ep0_out_start(GET_CORE_IF(pcd), pcd);
01213 }
01214 
01219 static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
01220 {
01221         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
01222         if (pcd->ep0state == EP0_STALL) {
01223                 DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
01224                 return;
01225         }
01226         pcd->ep0state = EP0_OUT_STATUS_PHASE;
01227 
01228         DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
01229         ep0->dwc_ep.xfer_len = 0;
01230         ep0->dwc_ep.xfer_count = 0;
01231         ep0->dwc_ep.is_in = 0;
01232         ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
01233         dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
01234 
01235         /* Prepare for more SETUP Packets */
01236         if (GET_CORE_IF(pcd)->dma_enable == 0) {
01237                 ep0_out_start(GET_CORE_IF(pcd), pcd);
01238         }
01239 }
01240 
01245 static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
01246 {
01247         if (ep->dwc_ep.stall_clear_flag == 0)
01248                 dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
01249 
01250         /* Reactive the EP */
01251         dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
01252         if (ep->stopped) {
01253                 ep->stopped = 0;
01254                 /* If there is a request in the EP queue start it */
01255 
01259                 /*
01260                  * Above fixme is solved by implmenting a tasklet to call the
01261                  * start_next_request(), outside of interrupt context at some
01262                  * time after the current time, after a clear-halt setup packet.
01263                  * Still need to implement ep mismatch in the future if a gadget
01264                  * ever uses more than one endpoint at once
01265                  */
01266                 ep->queue_sof = 1;
01267                 DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
01268         }
01269         /* Start Control Status Phase */
01270         do_setup_in_status_phase(pcd);
01271 }
01272 
01284 void do_test_mode(void *data)
01285 {
01286         dctl_data_t dctl;
01287         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
01288         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01289         int test_mode = pcd->test_mode;
01290 
01291 //        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
01292 
01293         dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl);
01294         switch (test_mode) {
01295         case 1:         // TEST_J
01296                 dctl.b.tstctl = 1;
01297                 break;
01298 
01299         case 2:         // TEST_K
01300                 dctl.b.tstctl = 2;
01301                 break;
01302 
01303         case 3:         // TEST_SE0_NAK
01304                 dctl.b.tstctl = 3;
01305                 break;
01306 
01307         case 4:         // TEST_PACKET
01308                 dctl.b.tstctl = 4;
01309                 break;
01310 
01311         case 5:         // TEST_FORCE_ENABLE
01312                 dctl.b.tstctl = 5;
01313                 break;
01314         }
01315         dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
01316 }
01317 
01321 static inline void do_get_status(dwc_otg_pcd_t * pcd)
01322 {
01323         usb_device_request_t ctrl = pcd->setup_pkt->req;
01324         dwc_otg_pcd_ep_t *ep;
01325         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
01326         uint16_t *status = pcd->status_buf;
01327 
01328 #ifdef DEBUG_EP0
01329         DWC_DEBUGPL(DBG_PCD,
01330                     "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
01331                     ctrl.bmRequestType, ctrl.bRequest,
01332                     UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
01333                     UGETW(ctrl.wLength));
01334 #endif
01335 
01336         switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
01337         case UT_DEVICE:
01338                 *status = 0x1;  /* Self powered */
01339                 *status |= pcd->remote_wakeup_enable << 1;
01340                 break;
01341 
01342         case UT_INTERFACE:
01343                 *status = 0;
01344                 break;
01345 
01346         case UT_ENDPOINT:
01347                 ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
01348                 if (ep == 0 || UGETW(ctrl.wLength) > 2) {
01349                         ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
01350                         return;
01351                 }
01353                 *status = ep->stopped;
01354                 break;
01355         }
01356         pcd->ep0_pending = 1;
01357         ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
01358         ep0->dwc_ep.xfer_buff = (uint8_t *) status;
01359         ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
01360         ep0->dwc_ep.xfer_len = 2;
01361         ep0->dwc_ep.xfer_count = 0;
01362         ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
01363         dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
01364 }
01365 
01369 static inline void do_set_feature(dwc_otg_pcd_t * pcd)
01370 {
01371         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01372         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
01373         usb_device_request_t ctrl = pcd->setup_pkt->req;
01374         dwc_otg_pcd_ep_t *ep = 0;
01375         int32_t otg_cap_param = core_if->core_params->otg_cap;
01376         gotgctl_data_t gotgctl = {.d32 = 0 };
01377 
01378         DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
01379                     ctrl.bmRequestType, ctrl.bRequest,
01380                     UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
01381                     UGETW(ctrl.wLength));
01382         DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
01383 
01384         switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
01385         case UT_DEVICE:
01386                 switch (UGETW(ctrl.wValue)) {
01387                 case UF_DEVICE_REMOTE_WAKEUP:
01388                         pcd->remote_wakeup_enable = 1;
01389                         break;
01390 
01391                 case UF_TEST_MODE:
01392                         /* Setup the Test Mode tasklet to do the Test
01393                          * Packet generation after the SETUP Status
01394                          * phase has completed. */
01395 
01399                         pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
01400                         DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
01401                         break;
01402 
01403                 case UF_DEVICE_B_HNP_ENABLE:
01404                         DWC_DEBUGPL(DBG_PCDV,
01405                                     "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
01406 
01407                         /* dev may initiate HNP */
01408                         if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
01409                                 pcd->b_hnp_enable = 1;
01410                                 dwc_otg_pcd_update_otg(pcd, 0);
01411                                 DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
01414                                 gotgctl.b.devhnpen = 1;
01415                                 gotgctl.b.hnpreq = 1;
01416                                 dwc_write_reg32(&global_regs->gotgctl,
01417                                                 gotgctl.d32);
01418                         } else {
01419                                 ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
01420                         }
01421                         break;
01422 
01423                 case UF_DEVICE_A_HNP_SUPPORT:
01424                         /* RH port supports HNP */
01425                         DWC_DEBUGPL(DBG_PCDV,
01426                                     "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
01427                         if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
01428                                 pcd->a_hnp_support = 1;
01429                                 dwc_otg_pcd_update_otg(pcd, 0);
01430                         } else {
01431                                 ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
01432                         }
01433                         break;
01434 
01435                 case UF_DEVICE_A_ALT_HNP_SUPPORT:
01436                         /* other RH port does */
01437                         DWC_DEBUGPL(DBG_PCDV,
01438                                     "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
01439                         if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
01440                                 pcd->a_alt_hnp_support = 1;
01441                                 dwc_otg_pcd_update_otg(pcd, 0);
01442                         } else {
01443                                 ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
01444                         }
01445                         break;
01446                 }
01447                 do_setup_in_status_phase(pcd);
01448                 break;
01449 
01450         case UT_INTERFACE:
01451                 do_gadget_setup(pcd, &ctrl);
01452                 break;
01453 
01454         case UT_ENDPOINT:
01455                 if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
01456                         ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
01457                         if (ep == 0) {
01458                                 ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
01459                                 return;
01460                         }
01461                         ep->stopped = 1;
01462                         dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
01463                 }
01464                 do_setup_in_status_phase(pcd);
01465                 break;
01466         }
01467 }
01468 
01472 static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
01473 {
01474         usb_device_request_t ctrl = pcd->setup_pkt->req;
01475         dwc_otg_pcd_ep_t *ep = 0;
01476 
01477         DWC_DEBUGPL(DBG_PCD,
01478                     "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
01479                     ctrl.bmRequestType, ctrl.bRequest,
01480                     UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
01481                     UGETW(ctrl.wLength));
01482 
01483         switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
01484         case UT_DEVICE:
01485                 switch (UGETW(ctrl.wValue)) {
01486                 case UF_DEVICE_REMOTE_WAKEUP:
01487                         pcd->remote_wakeup_enable = 0;
01488                         break;
01489 
01490                 case UF_TEST_MODE:
01492                         break;
01493                 }
01494                 do_setup_in_status_phase(pcd);
01495                 break;
01496 
01497         case UT_ENDPOINT:
01498                 ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
01499                 if (ep == 0) {
01500                         ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
01501                         return;
01502                 }
01503 
01504                 pcd_clear_halt(pcd, ep);
01505 
01506                 break;
01507         }
01508 }
01509 
01513 static inline void do_set_address(dwc_otg_pcd_t * pcd)
01514 {
01515         dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
01516         usb_device_request_t ctrl = pcd->setup_pkt->req;
01517 
01518         if (ctrl.bmRequestType == UT_DEVICE) {
01519                 dcfg_data_t dcfg = {.d32 = 0 };
01520 
01521 #ifdef DEBUG_EP0
01522 //                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
01523 #endif
01524                 dcfg.b.devaddr = UGETW(ctrl.wValue);
01525                 dwc_modify_reg32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
01526                 do_setup_in_status_phase(pcd);
01527         }
01528 }
01529 
01580 static inline void pcd_setup(dwc_otg_pcd_t * pcd)
01581 {
01582         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01583         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
01584         usb_device_request_t ctrl = pcd->setup_pkt->req;
01585         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
01586 
01587         deptsiz0_data_t doeptsize0 = {.d32 = 0 };
01588 
01589 #ifdef DWC_UTE_CFI
01590         int retval = 0;
01591         struct cfi_usb_ctrlrequest cfi_req;
01592 #endif
01593 
01594 #ifdef DEBUG_EP0
01595         DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
01596                     ctrl.bmRequestType, ctrl.bRequest,
01597                     UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
01598                     UGETW(ctrl.wLength));
01599 #endif
01600 
01601         doeptsize0.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doeptsiz);
01602 
01605         if (core_if->dma_enable && core_if->dma_desc_enable == 0
01606             && (doeptsize0.b.supcnt < 2)) {
01607                 DWC_ERROR
01608                     ("\n\n-----------    CANNOT handle > 1 setup packet in DMA mode\n\n");
01609         }
01610 
01611         /* Clean up the request queue */
01612         dwc_otg_request_nuke(ep0);
01613         ep0->stopped = 0;
01614 
01615         if (ctrl.bmRequestType & UE_DIR_IN) {
01616                 ep0->dwc_ep.is_in = 1;
01617                 pcd->ep0state = EP0_IN_DATA_PHASE;
01618         } else {
01619                 ep0->dwc_ep.is_in = 0;
01620                 pcd->ep0state = EP0_OUT_DATA_PHASE;
01621         }
01622 
01623         if (UGETW(ctrl.wLength) == 0) {
01624                 ep0->dwc_ep.is_in = 1;
01625                 pcd->ep0state = EP0_IN_STATUS_PHASE;
01626         }
01627 
01628         if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
01629 
01630 #ifdef DWC_UTE_CFI
01631                 DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
01632 
01633                 //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ctrl.bRequestType, ctrl.bRequest);
01634                 if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
01635                         if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
01636                                 retval = cfi_setup(pcd, &cfi_req);
01637                                 if (retval < 0) {
01638                                         ep0_do_stall(pcd, retval);
01639                                         pcd->ep0_pending = 0;
01640                                         return;
01641                                 }
01642 
01643                                 /* if need gadget setup then call it and check the retval */
01644                                 if (pcd->cfi->need_gadget_att) {
01645                                         retval =
01646                                             cfi_gadget_setup(pcd,
01647                                                              &pcd->cfi->
01648                                                              ctrl_req);
01649                                         if (retval < 0) {
01650                                                 pcd->ep0_pending = 0;
01651                                                 return;
01652                                         }
01653                                 }
01654 
01655                                 if (pcd->cfi->need_status_in_complete) {
01656                                         do_setup_in_status_phase(pcd);
01657                                 }
01658                                 return;
01659                         }
01660                 }
01661 #endif
01662 
01663                 /* handle non-standard (class/vendor) requests in the gadget driver */
01664                 do_gadget_setup(pcd, &ctrl);
01665                 return;
01666         }
01667 
01670 
01671 
01672 
01673         switch (ctrl.bRequest) {
01674         case UR_GET_STATUS:
01675                 do_get_status(pcd);
01676                 break;
01677 
01678         case UR_CLEAR_FEATURE:
01679                 do_clear_feature(pcd);
01680                 break;
01681 
01682         case UR_SET_FEATURE:
01683                 do_set_feature(pcd);
01684                 break;
01685 
01686         case UR_SET_ADDRESS:
01687                 do_set_address(pcd);
01688                 break;
01689 
01690         case UR_SET_INTERFACE:
01691         case UR_SET_CONFIG:
01692 //              _pcd->request_config = 1;       /* Configuration changed */
01693                 do_gadget_setup(pcd, &ctrl);
01694                 break;
01695 
01696         case UR_SYNCH_FRAME:
01697                 do_gadget_setup(pcd, &ctrl);
01698                 break;
01699 
01700         default:
01701                 /* Call the Gadget Driver's setup functions */
01702                 do_gadget_setup(pcd, &ctrl);
01703                 break;
01704         }
01705 }
01706 
01710 static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
01711 {
01712         dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
01713         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
01714         dwc_otg_dev_in_ep_regs_t *in_ep_regs =
01715             dev_if->in_ep_regs[ep->dwc_ep.num];
01716 #ifdef DEBUG_EP0
01717         dwc_otg_dev_out_ep_regs_t *out_ep_regs =
01718             dev_if->out_ep_regs[ep->dwc_ep.num];
01719 #endif
01720         deptsiz0_data_t deptsiz;
01721         dev_dma_desc_sts_t desc_sts;
01722         dwc_otg_pcd_request_t *req;
01723         int is_last = 0;
01724         dwc_otg_pcd_t *pcd = ep->pcd;
01725 
01726 #ifdef DWC_UTE_CFI
01727         struct cfi_usb_ctrlrequest *ctrlreq;
01728         int retval = -DWC_E_NOT_SUPPORTED;
01729 #endif
01730 
01731         if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
01732                 if (ep->dwc_ep.is_in) {
01733 #ifdef DEBUG_EP0
01734                         DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
01735 #endif
01736                         do_setup_out_status_phase(pcd);
01737                 } else {
01738 #ifdef DEBUG_EP0
01739                         DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
01740 #endif
01741 
01742 #ifdef DWC_UTE_CFI
01743                         ctrlreq = &pcd->cfi->ctrl_req;
01744 
01745                         if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
01746                                 if (ctrlreq->bRequest > 0xB0
01747                                     && ctrlreq->bRequest < 0xBF) {
01748 
01749                                         /* Return if the PCD failed to handle the request */
01750                                         if ((retval =
01751                                              pcd->cfi->ops.
01752                                              ctrl_write_complete(pcd->cfi,
01753                                                                  pcd)) < 0) {
01754                                                 CFI_INFO
01755                                                     ("ERROR setting a new value in the PCD(%d)\n",
01756                                                      retval);
01757                                                 ep0_do_stall(pcd, retval);
01758                                                 pcd->ep0_pending = 0;
01759                                                 return 0;
01760                                         }
01761 
01762                                         /* If the gadget needs to be notified on the request */
01763                                         if (pcd->cfi->need_gadget_att == 1) {
01764                                                 //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
01765                                                 retval =
01766                                                     cfi_gadget_setup(pcd,
01767                                                                      &pcd->cfi->
01768                                                                      ctrl_req);
01769 
01770                                                 /* Return from the function if the gadget failed to process
01771                                                  * the request properly - this should never happen !!!
01772                                                  */
01773                                                 if (retval < 0) {
01774                                                         CFI_INFO
01775                                                             ("ERROR setting a new value in the gadget(%d)\n",
01776                                                              retval);
01777                                                         pcd->ep0_pending = 0;
01778                                                         return 0;
01779                                                 }
01780                                         }
01781 
01782                                         CFI_INFO("%s: RETVAL=%d\n", __func__,
01783                                                  retval);
01784                                         /* If we hit here then the PCD and the gadget has properly
01785                                          * handled the request - so send the ZLP IN to the host.
01786                                          */
01787                                         /* @todo: MAS - decide whether we need to start the setup
01788                                          * stage based on the need_setup value of the cfi object
01789                                          */
01790                                         do_setup_in_status_phase(pcd);
01791                                         pcd->ep0_pending = 0;
01792                                         return 1;
01793                                 }
01794                         }
01795 #endif
01796 
01797                         do_setup_in_status_phase(pcd);
01798                 }
01799                 pcd->ep0_pending = 0;
01800                 return 1;
01801         }
01802 
01803         if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
01804                 return 0;
01805         }
01806         req = DWC_CIRCLEQ_FIRST(&ep->queue);
01807 
01808         if (pcd->ep0state == EP0_OUT_STATUS_PHASE
01809             || pcd->ep0state == EP0_IN_STATUS_PHASE) {
01810                 is_last = 1;
01811         } else if (ep->dwc_ep.is_in) {
01812                 deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz);
01813                 if (core_if->dma_desc_enable != 0)
01814                         desc_sts = dev_if->in_desc_addr->status;
01815 #ifdef DEBUG_EP0
01816                 DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",
01817                             ep->dwc_ep.num, ep->dwc_ep.xfer_len,
01818                             deptsiz.b.xfersize, deptsiz.b.pktcnt);
01819 #endif
01820 
01821                 if (((core_if->dma_desc_enable == 0)
01822                      && (deptsiz.b.xfersize == 0))
01823                     || ((core_if->dma_desc_enable != 0)
01824                         && (desc_sts.b.bytes == 0))) {
01825                         req->actual = ep->dwc_ep.xfer_count;
01826                         /* Is a Zero Len Packet needed? */
01827                         if (req->sent_zlp) {
01828 #ifdef DEBUG_EP0
01829                                 DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
01830 #endif
01831                                 req->sent_zlp = 0;
01832                         }
01833                         do_setup_out_status_phase(pcd);
01834                 }
01835         } else {
01836                 /* ep0-OUT */
01837 #ifdef DEBUG_EP0
01838                 deptsiz.d32 = dwc_read_reg32(&out_ep_regs->doeptsiz);
01839                 DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
01840                             ep->dwc_ep.num, ep->dwc_ep.xfer_len,
01841                             deptsiz.b.xfersize, deptsiz.b.pktcnt);
01842 #endif
01843                 req->actual = ep->dwc_ep.xfer_count;
01844 
01845                 /* Is a Zero Len Packet needed? */
01846                 if (req->sent_zlp) {
01847 #ifdef DEBUG_EP0
01848                         DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
01849 #endif
01850                         req->sent_zlp = 0;
01851                 }
01852                 if (core_if->dma_desc_enable == 0)
01853                         do_setup_in_status_phase(pcd);
01854         }
01855 
01856         /* Complete the request */
01857         if (is_last) {
01858                 dwc_otg_request_done(ep, req, 0);
01859                 ep->dwc_ep.start_xfer_buff = 0;
01860                 ep->dwc_ep.xfer_buff = 0;
01861                 ep->dwc_ep.xfer_len = 0;
01862                 return 1;
01863         }
01864         return 0;
01865 }
01866 
01867 #ifdef DWC_UTE_CFI
01868 
01874 static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
01875 {
01876         int32_t ret = 0;
01877         int i;
01878         struct dwc_otg_dma_desc *ddesc = NULL;
01879         struct cfi_ep *cfiep;
01880 
01881         /* See if the pcd_ep has its respective cfi_ep mapped */
01882         cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
01883         if (!cfiep) {
01884                 CFI_INFO("%s: Failed to find ep\n", __func__);
01885                 return -1;
01886         }
01887 
01888         ddesc = ep->dwc_ep.descs;
01889 
01890         for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
01891 
01892 #if defined(PRINT_CFI_DMA_DESCS)
01893                 print_desc(ddesc, ep->ep.name, i);
01894 #endif
01895                 ret += ddesc->status.b.bytes;
01896                 ddesc++;
01897         }
01898 
01899         if (ret)
01900                 CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
01901                          ret);
01902 
01903         return ret;
01904 }
01905 #endif
01906 
01911 static void complete_ep(dwc_otg_pcd_ep_t * ep)
01912 {
01913         dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
01914         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
01915         dwc_otg_dev_in_ep_regs_t *in_ep_regs =
01916             dev_if->in_ep_regs[ep->dwc_ep.num];
01917         deptsiz_data_t deptsiz;
01918         dev_dma_desc_sts_t desc_sts;
01919         dwc_otg_pcd_request_t *req = 0;
01920         dwc_otg_dev_dma_desc_t *dma_desc;
01921         uint32_t byte_count = 0;
01922         int is_last = 0;
01923         int i;
01924 
01925         DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
01926                     (ep->dwc_ep.is_in ? "IN" : "OUT"));
01927 
01928         /* Get any pending requests */
01929         if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
01930                 req = DWC_CIRCLEQ_FIRST(&ep->queue);
01931                 if (!req) {
01932                         DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
01933                         return;
01934                 }
01935         } else {
01936                 DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
01937                 return;
01938         }
01939 
01940         DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
01941 
01942         if (ep->dwc_ep.is_in) {
01943                 deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz);
01944 
01945                 if (core_if->dma_enable) {
01946                         if (core_if->dma_desc_enable == 0) {
01947                                 if (deptsiz.b.xfersize == 0
01948                                     && deptsiz.b.pktcnt == 0) {
01949                                         byte_count =
01950                                             ep->dwc_ep.xfer_len -
01951                                             ep->dwc_ep.xfer_count;
01952 
01953                                         ep->dwc_ep.xfer_buff += byte_count;
01954                                         ep->dwc_ep.dma_addr += byte_count;
01955                                         ep->dwc_ep.xfer_count += byte_count;
01956 
01957                                         DWC_DEBUGPL(DBG_PCDV,
01958                                                     "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
01959                                                     ep->dwc_ep.num,
01960                                                     (ep->dwc_ep.
01961                                                      is_in ? "IN" : "OUT"),
01962                                                     ep->dwc_ep.xfer_len,
01963                                                     deptsiz.b.xfersize,
01964                                                     deptsiz.b.pktcnt);
01965 
01966                                         if (ep->dwc_ep.xfer_len <
01967                                             ep->dwc_ep.total_len) {
01968                                                 dwc_otg_ep_start_transfer
01969                                                     (core_if, &ep->dwc_ep);
01970                                         } else if (ep->dwc_ep.sent_zlp) {
01971                                                 /*      
01972                                                  * This fragment of code should initiate 0 
01973                                                  * length trasfer in case if it is queued
01974                                                  * a trasfer with size divisible to EPs max 
01975                                                  * packet size and with usb_request zero field 
01976                                                  * is set, which means that after data is transfered, 
01977                                                  * it is also should be transfered 
01978                                                  * a 0 length packet at the end. For Slave and 
01979                                                  * Buffer DMA modes in this case SW has 
01980                                                  * to initiate 2 transfers one with transfer size, 
01981                                                  * and the second with 0 size. For Desriptor 
01982                                                  * DMA mode SW is able to initiate a transfer, 
01983                                                  * which will handle all the packets including 
01984                                                  * the last  0 legth.
01985                                                  */
01986                                                 ep->dwc_ep.sent_zlp = 0;
01987                                                 dwc_otg_ep_start_zl_transfer
01988                                                     (core_if, &ep->dwc_ep);
01989                                         } else {
01990                                                 is_last = 1;
01991                                         }
01992                                 } else {
01993                                         DWC_WARN
01994                                             ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
01995                                              ep->dwc_ep.num,
01996                                              (ep->dwc_ep.is_in ? "IN" : "OUT"),
01997                                              deptsiz.b.xfersize,
01998                                              deptsiz.b.pktcnt);
01999                                 }
02000                         } else {
02001                                 dma_desc = ep->dwc_ep.desc_addr;
02002                                 byte_count = 0;
02003                                 ep->dwc_ep.sent_zlp = 0;
02004 
02005 #ifdef DWC_UTE_CFI
02006                                 CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
02007                                          ep->dwc_ep.buff_mode);
02008                                 if (ep->dwc_ep.buff_mode != BM_STANDARD) {
02009                                         int residue;
02010 
02011                                         residue = cfi_calc_desc_residue(ep);
02012                                         if (residue < 0)
02013                                                 return;
02014 
02015                                         byte_count = residue;
02016                                 } else {
02017 #endif
02018                                         for (i = 0; i < ep->dwc_ep.desc_cnt;
02019                                              ++i) {
02020                                         desc_sts = dma_desc->status;
02021                                         byte_count += desc_sts.b.bytes;
02022                                         dma_desc++;
02023                                 }
02024 #ifdef DWC_UTE_CFI
02025                                 }
02026 #endif
02027                                 if (byte_count == 0) {
02028                                         ep->dwc_ep.xfer_count =
02029                                             ep->dwc_ep.total_len;
02030                                         is_last = 1;
02031                                 } else {
02032                                         DWC_WARN("Incomplete transfer\n");
02033                                 }
02034                         }
02035                 } else {
02036                         if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
02037                                 DWC_DEBUGPL(DBG_PCDV,
02038                                             "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
02039                                             ep->dwc_ep.num,
02040                                             ep->dwc_ep.is_in ? "IN" : "OUT",
02041                                             ep->dwc_ep.xfer_len,
02042                                             deptsiz.b.xfersize,
02043                                             deptsiz.b.pktcnt);
02044 
02045                                 /*      Check if the whole transfer was completed,  
02046                                  *      if no, setup transfer for next portion of data
02047                                  */
02048                                 if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
02049                                         dwc_otg_ep_start_transfer(core_if,
02050                                                                   &ep->dwc_ep);
02051                                 } else if (ep->dwc_ep.sent_zlp) {
02052                                         /*      
02053                                          * This fragment of code should initiate 0 
02054                                          * length trasfer in case if it is queued
02055                                          * a trasfer with size divisible to EPs max 
02056                                          * packet size and with usb_request zero field 
02057                                          * is set, which means that after data is transfered, 
02058                                          * it is also should be transfered 
02059                                          * a 0 length packet at the end. For Slave and 
02060                                          * Buffer DMA modes in this case SW has 
02061                                          * to initiate 2 transfers one with transfer size, 
02062                                          * and the second with 0 size. For Desriptor 
02063                                          * DMA mode SW is able to initiate a transfer, 
02064                                          * which will handle all the packets including 
02065                                          * the last  0 legth.
02066                                          */
02067                                         ep->dwc_ep.sent_zlp = 0;
02068                                         dwc_otg_ep_start_zl_transfer(core_if,
02069                                                                      &ep->
02070                                                                      dwc_ep);
02071                                 } else {
02072                                         is_last = 1;
02073                                 }
02074                         } else {
02075                                 DWC_WARN
02076                                     ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
02077                                      ep->dwc_ep.num,
02078                                      (ep->dwc_ep.is_in ? "IN" : "OUT"),
02079                                      deptsiz.b.xfersize, deptsiz.b.pktcnt);
02080                         }
02081                 }
02082         } else {
02083                 dwc_otg_dev_out_ep_regs_t *out_ep_regs =
02084                     dev_if->out_ep_regs[ep->dwc_ep.num];
02085                 desc_sts.d32 = 0;
02086                 if (core_if->dma_enable) {
02087                         if (core_if->dma_desc_enable) {
02088                                 dma_desc = ep->dwc_ep.desc_addr;
02089                                 byte_count = 0;
02090                                 ep->dwc_ep.sent_zlp = 0;
02091 
02092 #ifdef DWC_UTE_CFI
02093                                 CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
02094                                          ep->dwc_ep.buff_mode);
02095                                 if (ep->dwc_ep.buff_mode != BM_STANDARD) {
02096                                         int residue;
02097                                         residue = cfi_calc_desc_residue(ep);
02098                                         if (residue < 0)
02099                                                 return;
02100                                         byte_count = residue;
02101                                 } else {
02102 #endif
02103 
02104                                         for (i = 0; i < ep->dwc_ep.desc_cnt;
02105                                              ++i) {
02106                                         desc_sts = dma_desc->status;
02107                                         byte_count += desc_sts.b.bytes;
02108                                         dma_desc++;
02109                                 }
02110 
02111 #ifdef DWC_UTE_CFI
02112                                 }
02113 #endif
02114                                 ep->dwc_ep.xfer_count = ep->dwc_ep.total_len
02115                                     - byte_count +
02116                                     ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3);
02117                                 is_last = 1;
02118                         } else {
02119                                 deptsiz.d32 = 0;
02120                                 deptsiz.d32 =
02121                                     dwc_read_reg32(&out_ep_regs->doeptsiz);
02122 
02123                                 byte_count = (ep->dwc_ep.xfer_len -
02124                                               ep->dwc_ep.xfer_count -
02125                                               deptsiz.b.xfersize);
02126                                 ep->dwc_ep.xfer_buff += byte_count;
02127                                 ep->dwc_ep.dma_addr += byte_count;
02128                                 ep->dwc_ep.xfer_count += byte_count;
02129 
02130                                 /*      Check if the whole transfer was completed,  
02131                                  *      if no, setup transfer for next portion of data
02132                                  */
02133                                 if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
02134                                         dwc_otg_ep_start_transfer(core_if,
02135                                                                   &ep->dwc_ep);
02136                                 } else if (ep->dwc_ep.sent_zlp) {
02137                                         /*      
02138                                          * This fragment of code should initiate 0 
02139                                          * length trasfer in case if it is queued
02140                                          * a trasfer with size divisible to EPs max 
02141                                          * packet size and with usb_request zero field 
02142                                          * is set, which means that after data is transfered, 
02143                                          * it is also should be transfered 
02144                                          * a 0 length packet at the end. For Slave and 
02145                                          * Buffer DMA modes in this case SW has 
02146                                          * to initiate 2 transfers one with transfer size, 
02147                                          * and the second with 0 size. For Desriptor 
02148                                          * DMA mode SW is able to initiate a transfer, 
02149                                          * which will handle all the packets including 
02150                                          * the last  0 legth.
02151                                          */
02152                                         ep->dwc_ep.sent_zlp = 0;
02153                                         dwc_otg_ep_start_zl_transfer(core_if,
02154                                                                      &ep->
02155                                                                      dwc_ep);
02156                                 } else {
02157                                         is_last = 1;
02158                                 }
02159                         }
02160                 } else {
02161                         /*      Check if the whole transfer was completed,  
02162                          *      if no, setup transfer for next portion of data
02163                          */
02164                         if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
02165                                 dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
02166                         } else if (ep->dwc_ep.sent_zlp) {
02167                                 /*      
02168                                  * This fragment of code should initiate 0 
02169                                  * length trasfer in case if it is queued
02170                                  * a trasfer with size divisible to EPs max 
02171                                  * packet size and with usb_request zero field 
02172                                  * is set, which means that after data is transfered, 
02173                                  * it is also should be transfered 
02174                                  * a 0 length packet at the end. For Slave and 
02175                                  * Buffer DMA modes in this case SW has 
02176                                  * to initiate 2 transfers one with transfer size, 
02177                                  * and the second with 0 size. For Desriptor 
02178                                  * DMA mode SW is able to initiate a transfer, 
02179                                  * which will handle all the packets including 
02180                                  * the last  0 legth.
02181                                  */
02182                                 ep->dwc_ep.sent_zlp = 0;
02183                                 dwc_otg_ep_start_zl_transfer(core_if,
02184                                                              &ep->dwc_ep);
02185                         } else {
02186                                 is_last = 1;
02187                         }
02188                 }
02189 
02190                 DWC_DEBUGPL(DBG_PCDV,
02191                             "addr %p,    %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
02192                             &out_ep_regs->doeptsiz, ep->dwc_ep.num,
02193                             ep->dwc_ep.is_in ? "IN" : "OUT",
02194                             ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
02195                             deptsiz.b.xfersize, deptsiz.b.pktcnt);
02196         }
02197 
02198         /* Complete the request */
02199         if (is_last) {
02200 #ifdef DWC_UTE_CFI
02201                 if (ep->dwc_ep.buff_mode != BM_STANDARD) {
02202                         req->actual = ep->dwc_ep.cfi_req_len - byte_count;
02203                 } else {
02204 #endif
02205                 req->actual = ep->dwc_ep.xfer_count;
02206 #ifdef DWC_UTE_CFI
02207                 }
02208 #endif
02209 
02210                 dwc_otg_request_done(ep, req, 0);
02211 
02212                 ep->dwc_ep.start_xfer_buff = 0;
02213                 ep->dwc_ep.xfer_buff = 0;
02214                 ep->dwc_ep.xfer_len = 0;
02215 
02216                 /* If there is a request in the queue start it. */
02217                 start_next_request(ep);
02218         }
02219 }
02220 
02221 #ifdef DWC_EN_ISOC
02222 
02227 static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
02228 {
02229         dwc_ep_t *dwc_ep = &ep->dwc_ep;
02230         volatile uint32_t *addr;
02231         depctl_data_t depctl = {.d32 = 0 };
02232         dwc_otg_pcd_t *pcd = ep->pcd;
02233         dwc_otg_dev_dma_desc_t *dma_desc;
02234         int i;
02235 
02236         dma_desc =
02237             dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
02238 
02239         if (dwc_ep->is_in) {
02240                 dev_dma_desc_sts_t sts = {.d32 = 0 };
02241                 for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
02242                         sts.d32 = dma_desc->status.d32;
02243                         sts.b_iso_in.bs = BS_HOST_READY;
02244                         dma_desc->status.d32 = sts.d32;
02245                 }
02246         } else {
02247                 dev_dma_desc_sts_t sts = {.d32 = 0 };
02248                 for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
02249                         sts.d32 = dma_desc->status.d32;
02250                         sts.b_iso_out.bs = BS_HOST_READY;
02251                         dma_desc->status.d32 = sts.d32;
02252                 }
02253         }
02254 
02255         if (dwc_ep->is_in == 0) {
02256                 addr =
02257                     &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
02258                     doepctl;
02259         } else {
02260                 addr =
02261                     &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
02262         }
02263         depctl.b.epena = 1;
02264         dwc_modify_reg32(addr, depctl.d32, depctl.d32);
02265 }
02266 
02274 void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
02275 {
02276         deptsiz_data_t deptsiz = {.d32 = 0 };
02277         dma_addr_t dma_addr;
02278         uint32_t offset;
02279 
02280         if (ep->proc_buf_num)
02281                 dma_addr = ep->dma_addr1;
02282         else
02283                 dma_addr = ep->dma_addr0;
02284 
02285         if (ep->is_in) {
02286                 deptsiz.d32 =
02287                     dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
02288                                    dieptsiz);
02289                 offset = ep->data_per_frame;
02290         } else {
02291                 deptsiz.d32 =
02292                     dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
02293                                    doeptsiz);
02294                 offset =
02295                     ep->data_per_frame +
02296                     (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
02297         }
02298 
02299         if (!deptsiz.b.xfersize) {
02300                 ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
02301                 ep->pkt_info[ep->cur_pkt].offset =
02302                     ep->cur_pkt_dma_addr - dma_addr;
02303                 ep->pkt_info[ep->cur_pkt].status = 0;
02304         } else {
02305                 ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
02306                 ep->pkt_info[ep->cur_pkt].offset =
02307                     ep->cur_pkt_dma_addr - dma_addr;
02308                 ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
02309         }
02310         ep->cur_pkt_addr += offset;
02311         ep->cur_pkt_dma_addr += offset;
02312         ep->cur_pkt++;
02313 }
02314 
02322 static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
02323                                    dwc_ep_t * dwc_ep)
02324 {
02325         dwc_otg_dev_dma_desc_t *dma_desc;
02326         dev_dma_desc_sts_t sts = {.d32 = 0 };
02327         iso_pkt_info_t *iso_packet;
02328         uint32_t data_per_desc;
02329         uint32_t offset;
02330         int i, j;
02331 
02332         iso_packet = dwc_ep->pkt_info;
02333 
02336         if (dwc_ep->is_in == 0) {
02337                 dma_desc =
02338                     dwc_ep->iso_desc_addr +
02339                     dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
02340                 offset = 0;
02341 
02342                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
02343                      i += dwc_ep->pkt_per_frm) {
02344                         for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
02345                                 data_per_desc =
02346                                     ((j + 1) * dwc_ep->maxpacket >
02347                                      dwc_ep->data_per_frame) ? dwc_ep->
02348                                     data_per_frame -
02349                                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
02350                                 data_per_desc +=
02351                                     (data_per_desc % 4) ? (4 -
02352                                                            data_per_desc %
02353                                                            4) : 0;
02354 
02355                                 sts.d32 = dma_desc->status.d32;
02356 
02357                                 /* Write status in iso_packet_decsriptor  */
02358                                 iso_packet->status =
02359                                     sts.b_iso_out.rxsts +
02360                                     (sts.b_iso_out.bs ^ BS_DMA_DONE);
02361                                 if (iso_packet->status) {
02362                                         iso_packet->status = -DWC_E_NO_DATA;
02363                                 }
02364 
02365                                 /* Received data length */
02366                                 if (!sts.b_iso_out.rxbytes) {
02367                                         iso_packet->length =
02368                                             data_per_desc -
02369                                             sts.b_iso_out.rxbytes;
02370                                 } else {
02371                                         iso_packet->length =
02372                                             data_per_desc -
02373                                             sts.b_iso_out.rxbytes + (4 -
02374                                                                      dwc_ep->
02375                                                                      data_per_frame
02376                                                                      % 4);
02377                                 }
02378 
02379                                 iso_packet->offset = offset;
02380 
02381                                 offset += data_per_desc;
02382                                 dma_desc++;
02383                                 iso_packet++;
02384                         }
02385                 }
02386 
02387                 for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
02388                         data_per_desc =
02389                             ((j + 1) * dwc_ep->maxpacket >
02390                              dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
02391                             j * dwc_ep->maxpacket : dwc_ep->maxpacket;
02392                         data_per_desc +=
02393                             (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
02394 
02395                         sts.d32 = dma_desc->status.d32;
02396 
02397                         /* Write status in iso_packet_decsriptor  */
02398                         iso_packet->status =
02399                             sts.b_iso_out.rxsts +
02400                             (sts.b_iso_out.bs ^ BS_DMA_DONE);
02401                         if (iso_packet->status) {
02402                                 iso_packet->status = -DWC_E_NO_DATA;
02403                         }
02404 
02405                         /* Received data length */
02406                         iso_packet->length =
02407                             dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
02408 
02409                         iso_packet->offset = offset;
02410 
02411                         offset += data_per_desc;
02412                         iso_packet++;
02413                         dma_desc++;
02414                 }
02415 
02416                 sts.d32 = dma_desc->status.d32;
02417 
02418                 /* Write status in iso_packet_decsriptor  */
02419                 iso_packet->status =
02420                     sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
02421                 if (iso_packet->status) {
02422                         iso_packet->status = -DWC_E_NO_DATA;
02423                 }
02424                 /* Received data length */
02425                 if (!sts.b_iso_out.rxbytes) {
02426                         iso_packet->length =
02427                             dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
02428                 } else {
02429                         iso_packet->length =
02430                             dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
02431                             (4 - dwc_ep->data_per_frame % 4);
02432                 }
02433 
02434                 iso_packet->offset = offset;
02435         } else {
02438                 dma_desc =
02439                     dwc_ep->iso_desc_addr +
02440                     dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
02441 
02442                 for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
02443                         sts.d32 = dma_desc->status.d32;
02444 
02445                         /* Write status in iso packet descriptor */
02446                         iso_packet->status =
02447                             sts.b_iso_in.txsts +
02448                             (sts.b_iso_in.bs ^ BS_DMA_DONE);
02449                         if (iso_packet->status != 0) {
02450                                 iso_packet->status = -DWC_E_NO_DATA;
02451 
02452                         }
02453                         /* Bytes has been transfered */
02454                         iso_packet->length =
02455                             dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
02456 
02457                         dma_desc++;
02458                         iso_packet++;
02459                 }
02460 
02461                 sts.d32 = dma_desc->status.d32;
02462                 while (sts.b_iso_in.bs == BS_DMA_BUSY) {
02463                         sts.d32 = dma_desc->status.d32;
02464                 }
02465 
02466                 /* Write status in iso packet descriptor ??? do be done with ERROR codes */
02467                 iso_packet->status =
02468                     sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
02469                 if (iso_packet->status != 0) {
02470                         iso_packet->status = -DWC_E_NO_DATA;
02471                 }
02472 
02473                 /* Bytes has been transfered */
02474                 iso_packet->length =
02475                     dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
02476         }
02477 }
02478 
02486 static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
02487 {
02488         int i, j;
02489         dwc_otg_dev_dma_desc_t *dma_desc;
02490         dma_addr_t dma_ad;
02491         volatile uint32_t *addr;
02492         dev_dma_desc_sts_t sts = {.d32 = 0 };
02493         uint32_t data_per_desc;
02494 
02495         if (dwc_ep->is_in == 0) {
02496                 addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
02497         } else {
02498                 addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
02499         }
02500 
02501         if (dwc_ep->proc_buf_num == 0) {
02503                 dma_ad = dwc_ep->dma_addr0;
02504         } else {
02506                 dma_ad = dwc_ep->dma_addr1;
02507         }
02508 
02511         if (dwc_ep->is_in == 0) {
02512                 dma_desc =
02513                     dwc_ep->iso_desc_addr +
02514                     dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
02515 
02516                 sts.b_iso_out.bs = BS_HOST_READY;
02517                 sts.b_iso_out.rxsts = 0;
02518                 sts.b_iso_out.l = 0;
02519                 sts.b_iso_out.sp = 0;
02520                 sts.b_iso_out.ioc = 0;
02521                 sts.b_iso_out.pid = 0;
02522                 sts.b_iso_out.framenum = 0;
02523 
02524                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
02525                      i += dwc_ep->pkt_per_frm) {
02526                         for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
02527                                 data_per_desc =
02528                                     ((j + 1) * dwc_ep->maxpacket >
02529                                      dwc_ep->data_per_frame) ? dwc_ep->
02530                                     data_per_frame -
02531                                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
02532                                 data_per_desc +=
02533                                     (data_per_desc % 4) ? (4 -
02534                                                            data_per_desc %
02535                                                            4) : 0;
02536                                 sts.b_iso_out.rxbytes = data_per_desc;
02537                                 dma_desc->buf = dma_ad;
02538                                 dma_desc->status.d32 = sts.d32;
02539 
02540                                 dma_ad += data_per_desc;
02541                                 dma_desc++;
02542                         }
02543                 }
02544 
02545                 for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
02546 
02547                         data_per_desc =
02548                             ((j + 1) * dwc_ep->maxpacket >
02549                              dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
02550                             j * dwc_ep->maxpacket : dwc_ep->maxpacket;
02551                         data_per_desc +=
02552                             (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
02553                         sts.b_iso_out.rxbytes = data_per_desc;
02554 
02555                         dma_desc->buf = dma_ad;
02556                         dma_desc->status.d32 = sts.d32;
02557 
02558                         dma_desc++;
02559                         dma_ad += data_per_desc;
02560                 }
02561 
02562                 sts.b_iso_out.ioc = 1;
02563                 sts.b_iso_out.l = dwc_ep->proc_buf_num;
02564 
02565                 data_per_desc =
02566                     ((j + 1) * dwc_ep->maxpacket >
02567                      dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
02568                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
02569                 data_per_desc +=
02570                     (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
02571                 sts.b_iso_out.rxbytes = data_per_desc;
02572 
02573                 dma_desc->buf = dma_ad;
02574                 dma_desc->status.d32 = sts.d32;
02575         } else {
02578                 dma_desc =
02579                     dwc_ep->iso_desc_addr +
02580                     dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
02581 
02582                 sts.b_iso_in.bs = BS_HOST_READY;
02583                 sts.b_iso_in.txsts = 0;
02584                 sts.b_iso_in.sp = 0;
02585                 sts.b_iso_in.ioc = 0;
02586                 sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
02587                 sts.b_iso_in.framenum = dwc_ep->next_frame;
02588                 sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
02589                 sts.b_iso_in.l = 0;
02590 
02591                 for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
02592                         dma_desc->buf = dma_ad;
02593                         dma_desc->status.d32 = sts.d32;
02594 
02595                         sts.b_iso_in.framenum += dwc_ep->bInterval;
02596                         dma_ad += dwc_ep->data_per_frame;
02597                         dma_desc++;
02598                 }
02599 
02600                 sts.b_iso_in.ioc = 1;
02601                 sts.b_iso_in.l = dwc_ep->proc_buf_num;
02602 
02603                 dma_desc->buf = dma_ad;
02604                 dma_desc->status.d32 = sts.d32;
02605 
02606                 dwc_ep->next_frame =
02607                     sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
02608         }
02609         dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
02610 }
02611 
02620 static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
02621                                            dwc_ep_t * dwc_ep)
02622 {
02623         uint32_t dma_addr;
02624         uint32_t drp_pkt;
02625         uint32_t drp_pkt_cnt;
02626         deptsiz_data_t deptsiz = {.d32 = 0 };
02627         depctl_data_t depctl = {.d32 = 0 };
02628         int i;
02629 
02630         deptsiz.d32 =
02631             dwc_read_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->
02632                            doeptsiz);
02633 
02634         drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
02635         drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
02636 
02637         /* Setting dropped packets status */
02638         for (i = 0; i < drp_pkt_cnt; ++i) {
02639                 dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
02640                 drp_pkt++;
02641                 deptsiz.b.pktcnt--;
02642         }
02643 
02644         if (deptsiz.b.pktcnt > 0) {
02645                 deptsiz.b.xfersize =
02646                     dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
02647                                         deptsiz.b.pktcnt) * dwc_ep->maxpacket;
02648         } else {
02649                 deptsiz.b.xfersize = 0;
02650                 deptsiz.b.pktcnt = 0;
02651         }
02652 
02653         dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
02654                         deptsiz.d32);
02655 
02656         if (deptsiz.b.pktcnt > 0) {
02657                 if (dwc_ep->proc_buf_num) {
02658                         dma_addr =
02659                             dwc_ep->dma_addr1 + dwc_ep->xfer_len -
02660                             deptsiz.b.xfersize;
02661                 } else {
02662                         dma_addr =
02663                             dwc_ep->dma_addr0 + dwc_ep->xfer_len -
02664                             deptsiz.b.xfersize;;
02665                 }
02666 
02667                 dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->
02668                                 doepdma, dma_addr);
02669 
02671                 depctl.d32 = 0;
02672                 depctl.b.epena = 1;
02673                 depctl.b.cnak = 1;
02674 
02675                 dwc_modify_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->
02676                                  doepctl, depctl.d32, depctl.d32);
02677                 return 0;
02678         } else {
02679                 return 1;
02680         }
02681 }
02682 
02690 static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
02691 {
02692         int i, j;
02693         dma_addr_t dma_ad;
02694         iso_pkt_info_t *packet_info = ep->pkt_info;
02695         uint32_t offset;
02696         uint32_t frame_data;
02697         deptsiz_data_t deptsiz;
02698 
02699         if (ep->proc_buf_num == 0) {
02701                 dma_ad = ep->dma_addr0;
02702         } else {
02704                 dma_ad = ep->dma_addr1;
02705         }
02706 
02707         if (ep->is_in) {
02708                 deptsiz.d32 =
02709                     dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
02710                                    dieptsiz);
02711         } else {
02712                 deptsiz.d32 =
02713                     dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
02714                                    doeptsiz);
02715         }
02716 
02717         if (!deptsiz.b.xfersize) {
02718                 offset = 0;
02719                 for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
02720                         frame_data = ep->data_per_frame;
02721                         for (j = 0; j < ep->pkt_per_frm; ++j) {
02722 
02723                                 /* Packet status - is not set as initially 
02724                                  * it is set to 0 and if packet was sent 
02725                                  successfully, status field will remain 0*/
02726 
02727                                 /* Bytes has been transfered */
02728                                 packet_info->length =
02729                                     (ep->maxpacket <
02730                                      frame_data) ? ep->maxpacket : frame_data;
02731 
02732                                 /* Received packet offset */
02733                                 packet_info->offset = offset;
02734                                 offset += packet_info->length;
02735                                 frame_data -= packet_info->length;
02736 
02737                                 packet_info++;
02738                         }
02739                 }
02740                 return 1;
02741         } else {
02742                 /* This is a workaround for in case of Transfer Complete with 
02743                  * PktDrpSts interrupts merging - in this case Transfer complete 
02744                  * interrupt for Isoc Out Endpoint is asserted without PktDrpSts 
02745                  * set and with DOEPTSIZ register non zero. Investigations showed,
02746                  * that this happens when Out packet is dropped, but because of 
02747                  * interrupts merging during first interrupt handling PktDrpSts
02748                  * bit is cleared and for next merged interrupts it is not reset.
02749                  * In this case SW hadles the interrupt as if PktDrpSts bit is set.
02750                  */
02751                 if (ep->is_in) {
02752                         return 1;
02753                 } else {
02754                         return handle_iso_out_pkt_dropped(core_if, ep);
02755                 }
02756         }
02757 }
02758 
02766 static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
02767 {
02768         dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
02769         dwc_ep_t *dwc_ep = &ep->dwc_ep;
02770         uint8_t is_last = 0;
02771 
02772         if(ep->dwc_ep.next_frame == 0xffffffff) {
02773                 DWC_WARN("Next frame is not set!\n");
02774                 return;
02775         }
02776 
02777         if (core_if->dma_enable) {
02778                 if (core_if->dma_desc_enable) {
02779                         set_ddma_iso_pkts_info(core_if, dwc_ep);
02780                         reinit_ddma_iso_xfer(core_if, dwc_ep);
02781                         is_last = 1;
02782                 } else {
02783                         if (core_if->pti_enh_enable) {
02784                                 if (set_iso_pkts_info(core_if, dwc_ep)) {
02785                                         dwc_ep->proc_buf_num =
02786                                             (dwc_ep->proc_buf_num ^ 1) & 0x1;
02787                                         dwc_otg_iso_ep_start_buf_transfer
02788                                             (core_if, dwc_ep);
02789                                         is_last = 1;
02790                                 }
02791                         } else {
02792                                 set_current_pkt_info(core_if, dwc_ep);
02793                                 if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
02794                                         is_last = 1;
02795                                         dwc_ep->cur_pkt = 0;
02796                                         dwc_ep->proc_buf_num =
02797                                             (dwc_ep->proc_buf_num ^ 1) & 0x1;
02798                                         if (dwc_ep->proc_buf_num) {
02799                                                 dwc_ep->cur_pkt_addr =
02800                                                     dwc_ep->xfer_buff1;
02801                                                 dwc_ep->cur_pkt_dma_addr =
02802                                                     dwc_ep->dma_addr1;
02803                                         } else {
02804                                                 dwc_ep->cur_pkt_addr =
02805                                                     dwc_ep->xfer_buff0;
02806                                                 dwc_ep->cur_pkt_dma_addr =
02807                                                     dwc_ep->dma_addr0;
02808                                         }
02809 
02810                                 }
02811                                 dwc_otg_iso_ep_start_frm_transfer(core_if,
02812                                                                   dwc_ep);
02813                         }
02814                 }
02815         } else {
02816                 set_current_pkt_info(core_if, dwc_ep);
02817                 if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
02818                         is_last = 1;
02819                         dwc_ep->cur_pkt = 0;
02820                         dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
02821                         if (dwc_ep->proc_buf_num) {
02822                                 dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
02823                                 dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
02824                         } else {
02825                                 dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
02826                                 dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
02827                         }
02828 
02829                 }
02830                 dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
02831         }
02832         if (is_last)
02833                 dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
02834 }
02835 #endif                          /* DWC_EN_ISOC */
02836 
02843 static void handle_ep0(dwc_otg_pcd_t * pcd)
02844 {
02845         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
02846         dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
02847         dev_dma_desc_sts_t desc_sts;
02848         deptsiz0_data_t deptsiz;
02849         uint32_t byte_count;
02850 
02851 #ifdef DEBUG_EP0
02852         DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
02853         print_ep0_state(pcd);
02854 #endif
02855 
02856 //      DWC_PRINTF("HANDLE EP0\n");
02857 
02858         switch (pcd->ep0state) {
02859         case EP0_DISCONNECT:
02860                 break;
02861 
02862         case EP0_IDLE:
02863                 pcd->request_config = 0;
02864 
02865                 pcd_setup(pcd);
02866                 break;
02867 
02868         case EP0_IN_DATA_PHASE:
02869 #ifdef DEBUG_EP0
02870                 DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
02871                             ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
02872                             ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
02873 #endif
02874 
02875                 if (core_if->dma_enable != 0) {
02876                         /*
02877                          * For EP0 we can only program 1 packet at a time so we
02878                          * need to do the make calculations after each complete.
02879                          * Call write_packet to make the calculations, as in
02880                          * slave mode, and use those values to determine if we
02881                          * can complete.
02882                          */
02883                         if (core_if->dma_desc_enable == 0) {
02884                                 deptsiz.d32 =
02885                                     dwc_read_reg32(&core_if->dev_if->
02886                                                    in_ep_regs[0]->dieptsiz);
02887                                 byte_count =
02888                                     ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
02889                         } else {
02890                                 desc_sts =
02891                                     core_if->dev_if->in_desc_addr->status;
02892                                 byte_count =
02893                                     ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
02894                         }
02895                         ep0->dwc_ep.xfer_count += byte_count;
02896                         ep0->dwc_ep.xfer_buff += byte_count;
02897                         ep0->dwc_ep.dma_addr += byte_count;
02898                 }
02899                 if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
02900                         dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
02901                                                       &ep0->dwc_ep);
02902                         DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
02903                 } else if (ep0->dwc_ep.sent_zlp) {
02904                         dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
02905                                                       &ep0->dwc_ep);
02906                         ep0->dwc_ep.sent_zlp = 0;
02907                         DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
02908                 } else {
02909                         ep0_complete_request(ep0);
02910                         DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
02911                 }
02912                 break;
02913         case EP0_OUT_DATA_PHASE:
02914 #ifdef DEBUG_EP0
02915                 DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
02916                             ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
02917                             ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
02918 #endif
02919                 if (core_if->dma_enable != 0) {
02920                         if (core_if->dma_desc_enable == 0) {
02921                                 deptsiz.d32 =
02922                                     dwc_read_reg32(&core_if->dev_if->
02923                                                    out_ep_regs[0]->doeptsiz);
02924                                 byte_count =
02925                                     ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
02926                         } else {
02927                                 desc_sts =
02928                                     core_if->dev_if->out_desc_addr->status;
02929                                 byte_count =
02930                                     ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
02931                         }
02932                         ep0->dwc_ep.xfer_count += byte_count;
02933                         ep0->dwc_ep.xfer_buff += byte_count;
02934                         ep0->dwc_ep.dma_addr += byte_count;
02935                 }
02936                 if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
02937                         dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
02938                                                       &ep0->dwc_ep);
02939                         DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
02940                 } else if (ep0->dwc_ep.sent_zlp) {
02941                         dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
02942                                                       &ep0->dwc_ep);
02943                         ep0->dwc_ep.sent_zlp = 0;
02944                         DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
02945                 } else {
02946                         ep0_complete_request(ep0);
02947                         DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
02948                 }
02949                 break;
02950 
02951         case EP0_IN_STATUS_PHASE:
02952         case EP0_OUT_STATUS_PHASE:
02953                 DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
02954                 ep0_complete_request(ep0);
02955                 pcd->ep0state = EP0_IDLE;
02956                 ep0->stopped = 1;
02957                 ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
02958 
02959                 /* Prepare for more SETUP Packets */
02960                 if (core_if->dma_enable) {
02961                         ep0_out_start(core_if, pcd);
02962                 }
02963                 break;
02964 
02965         case EP0_STALL:
02966                 DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
02967                 break;
02968         }
02969 #ifdef DEBUG_EP0
02970         print_ep0_state(pcd);
02971 #endif
02972 }
02973 
02977 static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
02978 {
02979         dwc_otg_core_if_t *core_if;
02980         dwc_otg_dev_if_t *dev_if;
02981         deptsiz_data_t dieptsiz = {.d32 = 0 };
02982         dwc_otg_pcd_ep_t *ep;
02983 
02984         ep = get_in_ep(pcd, epnum);
02985 
02986 #ifdef DWC_EN_ISOC
02987         if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
02988                 return;
02989         }
02990 #endif                          /* DWC_EN_ISOC  */
02991 
02992         core_if = GET_CORE_IF(pcd);
02993         dev_if = core_if->dev_if;
02994 
02995         dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz);
02996 
02997         DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
02998                     " stopped=%d\n", ep->dwc_ep.xfer_buff,
02999                     ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
03000         /*
03001          * If xfersize is 0 and pktcnt in not 0, resend the last packet.
03002          */
03003         if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
03004             ep->dwc_ep.start_xfer_buff != 0) {
03005                 if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
03006                         ep->dwc_ep.xfer_count = 0;
03007                         ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
03008                         ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
03009                 } else {
03010                         ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
03011                         /* convert packet size to dwords. */
03012                         ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
03013                         ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
03014                 }
03015                 ep->stopped = 0;
03016                 DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
03017                             "xfer_len=%0x stopped=%d\n",
03018                             ep->dwc_ep.xfer_buff,
03019                             ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
03020                             ep->stopped);
03021                 if (epnum == 0) {
03022                         dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
03023                 } else {
03024                         dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
03025                 }
03026         }
03027 }
03028 
03032 static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
03033                                              const uint32_t epnum)
03034 {
03035         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
03036         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
03037         deptsiz_data_t dieptsiz = {.d32 = 0 };
03038         dctl_data_t dctl = {.d32 = 0 };
03039         dwc_otg_pcd_ep_t *ep;
03040         dwc_ep_t *dwc_ep;
03041 
03042         ep = get_in_ep(pcd, epnum);
03043         dwc_ep = &ep->dwc_ep;
03044 
03045         if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
03046                 dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
03047                 return;
03048         }
03049 
03050         DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
03051                     dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl));
03052         dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz);
03053 
03054         DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
03055                     dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
03056 
03057         if (ep->stopped) {
03058                 /* Flush the Tx FIFO */
03059                 dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
03060                 /* Clear the Global IN NP NAK */
03061                 dctl.d32 = 0;
03062                 dctl.b.cgnpinnak = 1;
03063                 dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, 0);
03064                 /* Restart the transaction */
03065                 if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
03066                         restart_transfer(pcd, epnum);
03067                 }
03068         } else {
03069                 /* Restart the transaction */
03070                 if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
03071                         restart_transfer(pcd, epnum);
03072                 }
03073                 DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
03074         }
03075 }
03076 
03080 static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
03081                                              const uint32_t epnum)
03082 {
03083         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
03084         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
03085 
03086 #ifdef DEBUG
03087         deptsiz_data_t dieptsiz = {.d32 = 0 };
03088         uint32_t num = 0;
03089 #endif
03090         dctl_data_t dctl = {.d32 = 0 };
03091         dwc_otg_pcd_ep_t *ep;
03092 
03093         gintmsk_data_t intr_mask = {.d32 = 0 };
03094 
03095         ep = get_in_ep(pcd, epnum);
03096 
03097         /* Disable the NP Tx Fifo Empty Interrrupt */
03098         if (!core_if->dma_enable) {
03099                 intr_mask.b.nptxfempty = 1;
03100                 dwc_modify_reg32(&core_if->core_global_regs->gintmsk,
03101                                  intr_mask.d32, 0);
03102         }
03105         /*
03106          * Non-periodic EP
03107          */
03108         /* Enable the Global IN NAK Effective Interrupt */
03109         intr_mask.b.ginnakeff = 1;
03110         dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
03111 
03112         /* Set Global IN NAK */
03113         dctl.b.sgnpinnak = 1;
03114         dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
03115 
03116         ep->stopped = 1;
03117 
03118 #ifdef DEBUG
03119         dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[num]->dieptsiz);
03120         DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
03121                     dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
03122 #endif
03123 
03124 #ifdef DISABLE_PERIODIC_EP
03125         /*
03126          * Set the NAK bit for this EP to
03127          * start the disable process.
03128          */
03129         diepctl.d32 = 0;
03130         diepctl.b.snak = 1;
03131         dwc_modify_reg32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
03132                          diepctl.d32);
03133         ep->disabling = 1;
03134         ep->stopped = 1;
03135 #endif
03136 }
03137 
03141 static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
03142                                             const uint32_t epnum)
03143 {
03145         dwc_otg_core_if_t *core_if;
03146         diepmsk_data_t intr_mask = {.d32 = 0 };
03147 
03148         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
03149         core_if = GET_CORE_IF(pcd);
03150         intr_mask.b.nak = 1;
03151 
03152         if (core_if->multiproc_int_enable) {
03153                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
03154                                  diepeachintmsk[epnum], intr_mask.d32, 0);
03155         } else {
03156                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->diepmsk,
03157                                  intr_mask.d32, 0);
03158         }
03159 
03160         return 1;
03161 }
03162 
03166 static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
03167                                                 const uint32_t epnum)
03168 {
03170         dwc_otg_core_if_t *core_if;
03171         doepmsk_data_t intr_mask = {.d32 = 0 };
03172 
03173         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
03174                    "OUT EP Babble");
03175         core_if = GET_CORE_IF(pcd);
03176         intr_mask.b.babble = 1;
03177 
03178         if (core_if->multiproc_int_enable) {
03179                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
03180                                  doepeachintmsk[epnum], intr_mask.d32, 0);
03181         } else {
03182                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk,
03183                                  intr_mask.d32, 0);
03184         }
03185 
03186         return 1;
03187 }
03188 
03192 static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
03193                                              const uint32_t epnum)
03194 {
03196         dwc_otg_core_if_t *core_if;
03197         doepmsk_data_t intr_mask = {.d32 = 0 };
03198 
03199         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
03200         core_if = GET_CORE_IF(pcd);
03201         intr_mask.b.nak = 1;
03202 
03203         if (core_if->multiproc_int_enable) {
03204                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
03205                                  doepeachintmsk[epnum], intr_mask.d32, 0);
03206         } else {
03207                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk,
03208                                  intr_mask.d32, 0);
03209         }
03210 
03211         return 1;
03212 }
03213 
03217 static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
03218                                               const uint32_t epnum)
03219 {
03221         dwc_otg_core_if_t *core_if;
03222         doepmsk_data_t intr_mask = {.d32 = 0 };
03223 
03224         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
03225         core_if = GET_CORE_IF(pcd);
03226         intr_mask.b.nyet = 1;
03227 
03228         if (core_if->multiproc_int_enable) {
03229                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
03230                                  doepeachintmsk[epnum], intr_mask.d32, 0);
03231         } else {
03232                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk,
03233                                  intr_mask.d32, 0);
03234         }
03235 
03236         return 1;
03237 }
03238 
03255 static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
03256 {
03257 #define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
03258 do { \
03259                 diepint_data_t diepint = {.d32=0}; \
03260                 diepint.b.__intr = 1; \
03261                 dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
03262                 diepint.d32); \
03263 } while (0)
03264 
03265         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
03266         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
03267         diepint_data_t diepint = {.d32 = 0 };
03268         dctl_data_t dctl = {.d32 = 0 };
03269         depctl_data_t depctl = {.d32 = 0 };
03270         uint32_t ep_intr;
03271         uint32_t epnum = 0;
03272         dwc_otg_pcd_ep_t *ep;
03273         dwc_ep_t *dwc_ep;
03274         gintmsk_data_t intr_mask = {.d32 = 0 };
03275 
03276         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
03277 
03278         /* Read in the device interrupt bits */
03279         ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
03280 
03281         /* Service the Device IN interrupts for each endpoint */
03282         while (ep_intr) {
03283                 if (ep_intr & 0x1) {
03284                         uint32_t empty_msk;
03285                         /* Get EP pointer */
03286                         ep = get_in_ep(pcd, epnum);
03287                         dwc_ep = &ep->dwc_ep;
03288 
03289                         depctl.d32 =
03290                             dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl);
03291                         empty_msk =
03292                             dwc_read_reg32(&dev_if->dev_global_regs->
03293                                            dtknqr4_fifoemptymsk);
03294 
03295                         DWC_DEBUGPL(DBG_PCDV,
03296                                     "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",
03297                                     epnum, empty_msk, depctl.d32);
03298 
03299                         DWC_DEBUGPL(DBG_PCD,
03300                                     "EP%d-%s: type=%d, mps=%d\n",
03301                                     dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
03302                                     dwc_ep->type, dwc_ep->maxpacket);
03303 
03304                         diepint.d32 =
03305                             dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
03306 
03307                         DWC_DEBUGPL(DBG_PCDV,
03308                                     "EP %d Interrupt Register - 0x%x\n", epnum,
03309                                     diepint.d32);
03310                         /* Transfer complete */
03311                         if (diepint.b.xfercompl) {
03312                                 /* Disable the NP Tx FIFO Empty
03313                                  * Interrrupt */
03314                                 if (core_if->en_multiple_tx_fifo == 0) {
03315                                         intr_mask.b.nptxfempty = 1;
03316                                         dwc_modify_reg32(&core_if->
03317                                                          core_global_regs->
03318                                                          gintmsk, intr_mask.d32,
03319                                                          0);
03320                                 } else {
03321                                         /* Disable the Tx FIFO Empty Interrupt for this EP */
03322                                         uint32_t fifoemptymsk =
03323                                             0x1 << dwc_ep->num;
03324                                         dwc_modify_reg32(&core_if->dev_if->
03325                                                          dev_global_regs->
03326                                                          dtknqr4_fifoemptymsk,
03327                                                          fifoemptymsk, 0);
03328                                 }
03329                                 /* Clear the bit in DIEPINTn for this interrupt */
03330                                 CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
03331 
03332                                 /* Complete the transfer */
03333                                 if (epnum == 0) {
03334                                         handle_ep0(pcd);
03335                                 }
03336 #ifdef DWC_EN_ISOC
03337                                 else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
03338                                         if (!ep->stopped)
03339                                                 complete_iso_ep(pcd, ep);
03340                                 }
03341 #endif                          /* DWC_EN_ISOC */
03342                                 else {
03343 
03344                                         complete_ep(ep);
03345                                 }
03346                         }
03347                         /* Endpoint disable      */
03348                         if (diepint.b.epdisabled) {
03349                                 DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
03350                                             epnum);
03351                                 handle_in_ep_disable_intr(pcd, epnum);
03352 
03353                                 /* Clear the bit in DIEPINTn for this interrupt */
03354                                 CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
03355                         }
03356                         /* AHB Error */
03357                         if (diepint.b.ahberr) {
03358                                 DWC_DEBUGPL(DBG_ANY, "EP%d IN AHB Error\n",
03359                                             epnum);
03360                                 /* Clear the bit in DIEPINTn for this interrupt */
03361                                 CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
03362                         }
03363                         /* TimeOUT Handshake (non-ISOC IN EPs) */
03364                         if (diepint.b.timeout) {
03365                                 DWC_DEBUGPL(DBG_ANY, "EP%d IN Time-out\n",
03366                                             epnum);
03367                                 handle_in_ep_timeout_intr(pcd, epnum);
03368 
03369                                 CLEAR_IN_EP_INTR(core_if, epnum, timeout);
03370                         }
03372                         if (diepint.b.intktxfemp) {
03373                                 DWC_DEBUGPL(DBG_ANY,
03374                                             "EP%d IN TKN TxFifo Empty\n",
03375                                             epnum);
03376                                 if (!ep->stopped && epnum != 0) {
03377 
03378                                         diepmsk_data_t diepmsk = {.d32 = 0 };
03379                                         diepmsk.b.intktxfemp = 1;
03380 
03381                                         if (core_if->multiproc_int_enable) {
03382                                                 dwc_modify_reg32(&dev_if->
03383                                                                  dev_global_regs->
03384                                                                  diepeachintmsk
03385                                                                  [epnum],
03386                                                                  diepmsk.d32,
03387                                                                  0);
03388                                         } else {
03389                                                 dwc_modify_reg32(&dev_if->
03390                                                                  dev_global_regs->
03391                                                                  diepmsk,
03392                                                                  diepmsk.d32,
03393                                                                  0);
03394                                         }
03395                                 } else if (core_if->dma_desc_enable
03396                                            && epnum == 0
03397                                            && pcd->ep0state ==
03398                                            EP0_OUT_STATUS_PHASE) {
03399                                         // EP0 IN set STALL
03400                                         depctl.d32 =
03401                                             dwc_read_reg32(&dev_if->
03402                                                            in_ep_regs[epnum]->
03403                                                            diepctl);
03404 
03405                                         /* set the disable and stall bits */
03406                                         if (depctl.b.epena) {
03407                                                 depctl.b.epdis = 1;
03408                                         }
03409                                         depctl.b.stall = 1;
03410                                         dwc_write_reg32(&dev_if->
03411                                                         in_ep_regs[epnum]->
03412                                                         diepctl, depctl.d32);
03413                                 }
03414                                 CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
03415                         }
03417                         if (diepint.b.intknepmis) {
03418                                 DWC_DEBUGPL(DBG_ANY,
03419                                             "EP%d IN TKN EP Mismatch\n", epnum);
03420                                 CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
03421                         }
03423                         if (diepint.b.inepnakeff) {
03424                                 DWC_DEBUGPL(DBG_ANY,
03425                                             "EP%d IN EP NAK Effective\n",
03426                                             epnum);
03427                                 /* Periodic EP */
03428                                 if (ep->disabling) {
03429                                         depctl.d32 = 0;
03430                                         depctl.b.snak = 1;
03431                                         depctl.b.epdis = 1;
03432                                         dwc_modify_reg32(&dev_if->
03433                                                          in_ep_regs[epnum]->
03434                                                          diepctl, depctl.d32,
03435                                                          depctl.d32);
03436                                 }
03437                                 CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
03438 
03439                         }
03440 
03442                         if (diepint.b.emptyintr) {
03443                                 DWC_DEBUGPL(DBG_ANY,
03444                                             "EP%d Tx FIFO Empty Intr \n",
03445                                             epnum);
03446                                 write_empty_tx_fifo(pcd, epnum);
03447 
03448                                 CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
03449 
03450                         }
03451 
03453                         if (diepint.b.bna) {
03454                                 CLEAR_IN_EP_INTR(core_if, epnum, bna);
03455                                 if (core_if->dma_desc_enable) {
03456 #ifdef DWC_EN_ISOC
03457                                         if (dwc_ep->type ==
03458                                             DWC_OTG_EP_TYPE_ISOC) {
03459                                                 /*
03460                                                  * This checking is performed to prevent first "false" BNA 
03461                                                  * handling occuring right after reconnect 
03462                                                  */
03463                                                 if (dwc_ep->next_frame !=
03464                                                     0xffffffff)
03465                                                         dwc_otg_pcd_handle_iso_bna
03466                                                             (ep);
03467                                         } else
03468 #endif                          /* DWC_EN_ISOC */
03469                                         {
03470                                                 dctl.d32 =
03471                                                     dwc_read_reg32(&dev_if->
03472                                                                    dev_global_regs->
03473                                                                    dctl);
03474 
03475                                                 /* If Global Continue on BNA is disabled - disable EP */
03476                                                 if (!dctl.b.gcontbna) {
03477                                                         depctl.d32 = 0;
03478                                                         depctl.b.snak = 1;
03479                                                         depctl.b.epdis = 1;
03480                                                         dwc_modify_reg32
03481                                                             (&dev_if->
03482                                                              in_ep_regs[epnum]->
03483                                                              diepctl,
03484                                                              depctl.d32,
03485                                                              depctl.d32);
03486                                                 } else {
03487                                                         start_next_request(ep);
03488                                                 }
03489                                         }
03490                                 }
03491                         }
03492                         /* NAK Interrutp */
03493                         if (diepint.b.nak) {
03494                                 DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
03495                                             epnum);
03496                                 handle_in_ep_nak_intr(pcd, epnum);
03497 
03498                                 CLEAR_IN_EP_INTR(core_if, epnum, nak);
03499                         }
03500                 }
03501                 epnum++;
03502                 ep_intr >>= 1;
03503         }
03504 
03505         return 1;
03506 #undef CLEAR_IN_EP_INTR
03507 }
03508 
03522 static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
03523 {
03524 #define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
03525 do { \
03526                 doepint_data_t doepint = {.d32=0}; \
03527                 doepint.b.__intr = 1; \
03528                 dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
03529                 doepint.d32); \
03530 } while (0)
03531 
03532         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
03533         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
03534         uint32_t ep_intr;
03535         doepint_data_t doepint = {.d32 = 0 };
03536         dctl_data_t dctl = {.d32 = 0 };
03537         depctl_data_t doepctl = {.d32 = 0 };
03538         uint32_t epnum = 0;
03539         dwc_otg_pcd_ep_t *ep;
03540         dwc_ep_t *dwc_ep;
03541 
03542         DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
03543 
03544         /* Read in the device interrupt bits */
03545         ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
03546 
03547         while (ep_intr) {
03548                 if (ep_intr & 0x1) {
03549                         /* Get EP pointer */
03550                         ep = get_out_ep(pcd, epnum);
03551                         dwc_ep = &ep->dwc_ep;
03552 
03553 #ifdef VERBOSE
03554                         DWC_DEBUGPL(DBG_PCDV,
03555                                     "EP%d-%s: type=%d, mps=%d\n",
03556                                     dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
03557                                     dwc_ep->type, dwc_ep->maxpacket);
03558 #endif
03559                         doepint.d32 =
03560                             dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
03561 
03562                         /* Transfer complete */
03563                         if (doepint.b.xfercompl) {
03564 
03565                                 if (epnum == 0) {
03566                                         /* Clear the bit in DOEPINTn for this interrupt */
03567                                         CLEAR_OUT_EP_INTR(core_if, epnum,
03568                                                           xfercompl);
03569                                         if (core_if->dma_desc_enable == 0
03570                                             || pcd->ep0state != EP0_IDLE)
03571                                                 handle_ep0(pcd);
03572 #ifdef DWC_EN_ISOC
03573                                 } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
03574                                         if (doepint.b.pktdrpsts == 0) {
03575                                                 /* Clear the bit in DOEPINTn for this interrupt */
03576                                                 CLEAR_OUT_EP_INTR(core_if,
03577                                                                   epnum,
03578                                                                   xfercompl);
03579                                                 complete_iso_ep(pcd, ep);
03580                                         } else {
03581 
03582                                                 doepint_data_t doepint = {.d32 =
03583                                                             0 };
03584                                                 doepint.b.xfercompl = 1;
03585                                                 doepint.b.pktdrpsts = 1;
03586                                                 dwc_write_reg32(&core_if->
03587                                                                 dev_if->
03588                                                                 out_ep_regs
03589                                                                 [epnum]->
03590                                                                 doepint,
03591                                                                 doepint.d32);
03592                                                 if (handle_iso_out_pkt_dropped
03593                                                     (core_if, dwc_ep)) {
03594                                                         complete_iso_ep(pcd,
03595                                                                         ep);
03596                                                 }
03597                                         }
03598 #endif                          /* DWC_EN_ISOC */
03599                                 } else {
03600                                         /* Clear the bit in DOEPINTn for this interrupt */
03601                                         CLEAR_OUT_EP_INTR(core_if, epnum,
03602                                                           xfercompl);
03603                                         complete_ep(ep);
03604                                 }
03605 
03606                         }
03607 
03608                         /* Endpoint disable      */
03609                         if (doepint.b.epdisabled) {
03610 
03611                                 /* Clear the bit in DOEPINTn for this interrupt */
03612                                 CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
03613                         }
03614                         /* AHB Error */
03615                         if (doepint.b.ahberr) {
03616                                 DWC_DEBUGPL(DBG_PCD, "EP%d OUT AHB Error\n",
03617                                             epnum);
03618                                 DWC_DEBUGPL(DBG_PCD, "EP DMA REG         %d \n",
03619                                             core_if->dev_if->
03620                                             out_ep_regs[epnum]->doepdma);
03621                                 CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
03622                         }
03623                         /* Setup Phase Done (contorl EPs) */
03624                         if (doepint.b.setup) {
03625 #ifdef DEBUG_EP0
03626                                 DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n",
03627                                             epnum);
03628 #endif
03629                                 CLEAR_OUT_EP_INTR(core_if, epnum, setup);
03630 
03631                                 handle_ep0(pcd);
03632                         }
03633 
03635                         if (doepint.b.bna) {
03636                                 CLEAR_OUT_EP_INTR(core_if, epnum, bna);
03637                                 if (core_if->dma_desc_enable) {
03638 #ifdef DWC_EN_ISOC
03639                                         if (dwc_ep->type ==
03640                                             DWC_OTG_EP_TYPE_ISOC) {
03641                                                 /*
03642                                                  * This checking is performed to prevent first "false" BNA 
03643                                                  * handling occuring right after reconnect 
03644                                                  */
03645                                                 if (dwc_ep->next_frame !=
03646                                                     0xffffffff)
03647                                                         dwc_otg_pcd_handle_iso_bna
03648                                                             (ep);
03649                                         } else
03650 #endif                          /* DWC_EN_ISOC */
03651                                         {
03652                                                 dctl.d32 =
03653                                                     dwc_read_reg32(&dev_if->
03654                                                                    dev_global_regs->
03655                                                                    dctl);
03656 
03657                                                 /* If Global Continue on BNA is disabled - disable EP */
03658                                                 if (!dctl.b.gcontbna) {
03659                                                         doepctl.d32 = 0;
03660                                                         doepctl.b.snak = 1;
03661                                                         doepctl.b.epdis = 1;
03662                                                         dwc_modify_reg32
03663                                                             (&dev_if->
03664                                                              out_ep_regs
03665                                                              [epnum]->doepctl,
03666                                                              doepctl.d32,
03667                                                              doepctl.d32);
03668                                                 } else {
03669                                                         start_next_request(ep);
03670                                                 }
03671                                         }
03672                                 }
03673                         }
03674                         if (doepint.b.stsphsercvd) {
03675                                 CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
03676                                 if (core_if->dma_desc_enable) {
03677                                         do_setup_in_status_phase(pcd);
03678                                 }
03679                         }
03680                         /* Babble Interrutp */
03681                         if (doepint.b.babble) {
03682                                 DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
03683                                             epnum);
03684                                 handle_out_ep_babble_intr(pcd, epnum);
03685 
03686                                 CLEAR_OUT_EP_INTR(core_if, epnum, babble);
03687                         }
03688                         /* NAK Interrutp */
03689                         if (doepint.b.nak) {
03690                                 DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
03691                                 handle_out_ep_nak_intr(pcd, epnum);
03692 
03693                                 CLEAR_OUT_EP_INTR(core_if, epnum, nak);
03694                         }
03695                         /* NYET Interrutp */
03696                         if (doepint.b.nyet) {
03697                                 DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
03698                                 handle_out_ep_nyet_intr(pcd, epnum);
03699 
03700                                 CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
03701                         }
03702                 }
03703 
03704                 epnum++;
03705                 ep_intr >>= 1;
03706         }
03707 
03708         return 1;
03709 
03710 #undef CLEAR_OUT_EP_INTR
03711 }
03712 
03725 int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
03726 {
03727         gintsts_data_t gintsts;
03728 
03729 #ifdef DWC_EN_ISOC
03730         dwc_otg_dev_if_t *dev_if;
03731         deptsiz_data_t deptsiz = {.d32 = 0 };
03732         depctl_data_t depctl = {.d32 = 0 };
03733         dsts_data_t dsts = {.d32 = 0 };
03734         dwc_ep_t *dwc_ep;
03735         int i;
03736 
03737         dev_if = GET_CORE_IF(pcd)->dev_if;
03738 
03739         for (i = 1; i <= dev_if->num_in_eps; ++i) {
03740                 dwc_ep = &pcd->in_ep[i].dwc_ep;
03741                 if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
03742                         deptsiz.d32 =
03743                             dwc_read_reg32(&dev_if->in_ep_regs[i]->dieptsiz);
03744                         depctl.d32 =
03745                             dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
03746 
03747                         if (depctl.b.epdis && deptsiz.d32) {
03748                                 set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
03749                                 if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
03750                                         dwc_ep->cur_pkt = 0;
03751                                         dwc_ep->proc_buf_num =
03752                                             (dwc_ep->proc_buf_num ^ 1) & 0x1;
03753 
03754                                         if (dwc_ep->proc_buf_num) {
03755                                                 dwc_ep->cur_pkt_addr =
03756                                                     dwc_ep->xfer_buff1;
03757                                                 dwc_ep->cur_pkt_dma_addr =
03758                                                     dwc_ep->dma_addr1;
03759                                         } else {
03760                                                 dwc_ep->cur_pkt_addr =
03761                                                     dwc_ep->xfer_buff0;
03762                                                 dwc_ep->cur_pkt_dma_addr =
03763                                                     dwc_ep->dma_addr0;
03764                                         }
03765 
03766                                 }
03767 
03768                                 dsts.d32 =
03769                                     dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
03770                                                    dev_global_regs->dsts);
03771                                 dwc_ep->next_frame = dsts.b.soffn;
03772 
03773                                 dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
03774                                                                   (pcd),
03775                                                                   dwc_ep);
03776                         }
03777                 }
03778         }
03779 
03780 #else
03781         gintmsk_data_t intr_mask = {.d32 = 0 };
03782         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
03783                    "IN ISOC Incomplete");
03784 
03785         intr_mask.b.incomplisoin = 1;
03786         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
03787                          intr_mask.d32, 0);
03788 #endif                          //DWC_EN_ISOC
03789 
03790         /* Clear interrupt */
03791         gintsts.d32 = 0;
03792         gintsts.b.incomplisoin = 1;
03793         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
03794                         gintsts.d32);
03795 
03796         return 1;
03797 }
03798 
03814 int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
03815 {
03816 
03817         gintsts_data_t gintsts;
03818 
03819 #ifdef DWC_EN_ISOC
03820         dwc_otg_dev_if_t *dev_if;
03821         deptsiz_data_t deptsiz = {.d32 = 0 };
03822         depctl_data_t depctl = {.d32 = 0 };
03823         dsts_data_t dsts = {.d32 = 0 };
03824         dwc_ep_t *dwc_ep;
03825         int i;
03826 
03827         dev_if = GET_CORE_IF(pcd)->dev_if;
03828 
03829         for (i = 1; i <= dev_if->num_out_eps; ++i) {
03830                 dwc_ep = &pcd->in_ep[i].dwc_ep;
03831                 if (pcd->out_ep[i].dwc_ep.active &&
03832                     pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
03833                         deptsiz.d32 =
03834                             dwc_read_reg32(&dev_if->out_ep_regs[i]->doeptsiz);
03835                         depctl.d32 =
03836                             dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl);
03837 
03838                         if (depctl.b.epdis && deptsiz.d32) {
03839                                 set_current_pkt_info(GET_CORE_IF(pcd),
03840                                                      &pcd->out_ep[i].dwc_ep);
03841                                 if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
03842                                         dwc_ep->cur_pkt = 0;
03843                                         dwc_ep->proc_buf_num =
03844                                             (dwc_ep->proc_buf_num ^ 1) & 0x1;
03845 
03846                                         if (dwc_ep->proc_buf_num) {
03847                                                 dwc_ep->cur_pkt_addr =
03848                                                     dwc_ep->xfer_buff1;
03849                                                 dwc_ep->cur_pkt_dma_addr =
03850                                                     dwc_ep->dma_addr1;
03851                                         } else {
03852                                                 dwc_ep->cur_pkt_addr =
03853                                                     dwc_ep->xfer_buff0;
03854                                                 dwc_ep->cur_pkt_dma_addr =
03855                                                     dwc_ep->dma_addr0;
03856                                         }
03857 
03858                                 }
03859 
03860                                 dsts.d32 =
03861                                     dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
03862                                                    dev_global_regs->dsts);
03863                                 dwc_ep->next_frame = dsts.b.soffn;
03864 
03865                                 dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
03866                                                                   (pcd),
03867                                                                   dwc_ep);
03868                         }
03869                 }
03870         }
03871 #else
03872 
03873         gintmsk_data_t intr_mask = {.d32 = 0 };
03874 
03875         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
03876                    "OUT ISOC Incomplete");
03877 
03878         intr_mask.b.incomplisoout = 1;
03879         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
03880                          intr_mask.d32, 0);
03881 
03882 #endif                          /* DWC_EN_ISOC */
03883 
03884         /* Clear interrupt */
03885         gintsts.d32 = 0;
03886         gintsts.b.incomplisoout = 1;
03887         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
03888                         gintsts.d32);
03889 
03890         return 1;
03891 }
03892 
03897 int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
03898 {
03899         dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
03900         depctl_data_t diepctl = {.d32 = 0 };
03901         depctl_data_t diepctl_rd = {.d32 = 0 };
03902         gintmsk_data_t intr_mask = {.d32 = 0 };
03903         gintsts_data_t gintsts;
03904         int i;
03905 
03906         DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
03907 
03908         /* Disable all active IN EPs */
03909         diepctl.b.epdis = 1;
03910         diepctl.b.snak = 1;
03911 
03912         for (i = 0; i <= dev_if->num_in_eps; i++) {
03913                 diepctl_rd.d32 =
03914                     dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
03915                 if (diepctl_rd.b.epena) {
03916                         dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl,
03917                                         diepctl.d32);
03918                 }
03919         }
03920         /* Disable the Global IN NAK Effective Interrupt */
03921         intr_mask.b.ginnakeff = 1;
03922         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
03923                          intr_mask.d32, 0);
03924 
03925         /* Clear interrupt */
03926         gintsts.d32 = 0;
03927         gintsts.b.ginnakeff = 1;
03928         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
03929                         gintsts.d32);
03930 
03931         return 1;
03932 }
03933 
03938 int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
03939 {
03940         gintmsk_data_t intr_mask = {.d32 = 0 };
03941         gintsts_data_t gintsts;
03942 
03943         DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
03944                    "Global IN NAK Effective\n");
03945         /* Disable the Global IN NAK Effective Interrupt */
03946         intr_mask.b.goutnakeff = 1;
03947         dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
03948                          intr_mask.d32, 0);
03949 
03950         /* Clear interrupt */
03951         gintsts.d32 = 0;
03952         gintsts.b.goutnakeff = 1;
03953         dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
03954                         gintsts.d32);
03955 
03956         return 1;
03957 }
03958 
03971 int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
03972 {
03973         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
03974 #ifdef VERBOSE
03975         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
03976 #endif
03977         gintsts_data_t gintr_status;
03978         int32_t retval = 0;
03979 
03980 #ifdef VERBOSE
03981         DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n",
03982                     __func__,
03983                     dwc_read_reg32(&global_regs->gintsts),
03984                     dwc_read_reg32(&global_regs->gintmsk));
03985 #endif
03986 
03987         if (dwc_otg_is_device_mode(core_if)) {
03988                 DWC_SPINLOCK(pcd->lock);
03989 #ifdef VERBOSE
03990                 DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",
03991                             __func__,
03992                             dwc_read_reg32(&global_regs->gintsts),
03993                             dwc_read_reg32(&global_regs->gintmsk));
03994 #endif
03995 
03996                 gintr_status.d32 = dwc_otg_read_core_intr(core_if);
03997 
03998                 DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
03999                             __func__, gintr_status.d32);
04000 
04001                 if (gintr_status.b.sofintr) {
04002                         retval |= dwc_otg_pcd_handle_sof_intr(pcd);
04003                 }
04004                 if (gintr_status.b.rxstsqlvl) {
04005                         retval |=
04006                             dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
04007                 }
04008                 if (gintr_status.b.nptxfempty) {
04009                         retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
04010                 }
04011                 if (gintr_status.b.ginnakeff) {
04012                         retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
04013                 }
04014                 if (gintr_status.b.goutnakeff) {
04015                         retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
04016                 }
04017                 if (gintr_status.b.i2cintr) {
04018                         retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
04019                 }
04020                 if (gintr_status.b.erlysuspend) {
04021                         retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
04022                 }
04023                 if (gintr_status.b.usbreset) {
04024                         retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
04025                 }
04026                 if (gintr_status.b.enumdone) {
04027                         retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
04028                 }
04029                 if (gintr_status.b.isooutdrop) {
04030                         retval |=
04031                             dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
04032                             (pcd);
04033                 }
04034                 if (gintr_status.b.eopframe) {
04035                         retval |=
04036                             dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
04037                 }
04038                 if (gintr_status.b.epmismatch) {
04039                         retval |= dwc_otg_pcd_handle_ep_mismatch_intr(core_if);
04040                 }
04041                 if (gintr_status.b.inepint) {
04042                         if (!core_if->multiproc_int_enable) {
04043                                 retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
04044                         }
04045                 }
04046                 if (gintr_status.b.outepintr) {
04047                         if (!core_if->multiproc_int_enable) {
04048                                 retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
04049                         }
04050                 }
04051                 if (gintr_status.b.incomplisoin) {
04052                         retval |=
04053                             dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
04054                 }
04055                 if (gintr_status.b.incomplisoout) {
04056                         retval |=
04057                             dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
04058                 }
04059 
04060                 /* In MPI mode De vice Endpoints intterrupts are asserted 
04061                  * without setting outepintr and inepint bits set, so these
04062                  * Interrupt handlers are called without checking these bit-fields
04063                  */
04064                 if (core_if->multiproc_int_enable) {
04065                         retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
04066                         retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
04067                 }
04068 #ifdef VERBOSE
04069                 DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
04070                             dwc_read_reg32(&global_regs->gintsts));
04071 #endif
04072                 DWC_SPINUNLOCK(pcd->lock);
04073         }
04074         return retval;
04075 }
04076 
04077 #endif                          /* DWC_HOST_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