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

dwc_otg_pcd.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
00003  * $Revision: #99 $
00004  * $Date: 2011/10/24 $
00005  * $Change: 1871160 $
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 
00051 #include "dwc_otg_pcd.h"
00052 
00053 #ifdef DWC_UTE_CFI
00054 #include "dwc_otg_cfi.h"
00055 
00056 extern int init_cfi(cfiobject_t * cfiobj);
00057 #endif
00058 
00062 static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
00063 {
00064         int i;
00065         if (pcd->ep0.priv == handle) {
00066                 return &pcd->ep0;
00067         }
00068         for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
00069                 if (pcd->in_ep[i].priv == handle)
00070                         return &pcd->in_ep[i];
00071                 if (pcd->out_ep[i].priv == handle)
00072                         return &pcd->out_ep[i];
00073         }
00074 
00075         return NULL;
00076 }
00077 
00081 void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
00082                           int32_t status)
00083 {
00084         unsigned stopped = ep->stopped;
00085         
00086         DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
00087         DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
00088 
00089         /* don't modify queue heads during completion callback */
00090         ep->stopped = 1;
00091         /* spin_unlock/spin_lock now done in fops->complete() */
00092         ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
00093                                 req->actual);
00094 
00095         if (ep->pcd->request_pending > 0) {
00096                 --ep->pcd->request_pending;
00097         }
00098 
00099         ep->stopped = stopped;
00100         DWC_FREE(req);
00101 }
00102 
00106 void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
00107 {
00108         dwc_otg_pcd_request_t *req;
00109 
00110         ep->stopped = 1;
00111 
00112         /* called with irqs blocked?? */
00113         while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
00114                 req = DWC_CIRCLEQ_FIRST(&ep->queue);
00115                 dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
00116         }
00117 }
00118 
00119 void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
00120                        const struct dwc_otg_pcd_function_ops *fops)
00121 {
00122         pcd->fops = fops;
00123 }
00124 
00131 static int32_t dwc_otg_pcd_start_cb(void *p)
00132 {
00133         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00134         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00135 
00136         /*
00137          * Initialized the Core for Device mode.
00138          */
00139         if (dwc_otg_is_device_mode(core_if)) {
00140                 dwc_otg_core_dev_init(core_if);
00141                 /* Set core_if's lock pointer to the pcd->lock */
00142                 core_if->lock = pcd->lock;
00143         }
00144         return 1;
00145 }
00146 
00148 #ifdef DWC_UTE_CFI
00149 uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
00150                               size_t buflen, int flags)
00151 {
00152         dwc_otg_pcd_ep_t *ep;
00153         ep = get_ep_from_handle(pcd, pep);
00154         if (!ep) {
00155                 DWC_WARN("bad ep\n");
00156                 return -DWC_E_INVALID;
00157         }
00158 
00159         return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
00160                                           flags);
00161 }
00162 #else
00163 uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
00164                               size_t buflen, int flags);
00165 #endif
00166 
00173 static int32_t dwc_otg_pcd_resume_cb(void *p)
00174 {
00175         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00176 
00177         if (pcd->fops->resume) {
00178                 pcd->fops->resume(pcd);
00179         }
00180 
00181         /* Stop the SRP timeout timer. */
00182         if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
00183             || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
00184                 if (GET_CORE_IF(pcd)->srp_timer_started) {
00185                         GET_CORE_IF(pcd)->srp_timer_started = 0;
00186                         DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
00187                 }
00188         }
00189         return 1;
00190 }
00191 
00197 static int32_t dwc_otg_pcd_suspend_cb(void *p)
00198 {
00199         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00200 
00201         if (pcd->fops->suspend) {
00202                 DWC_SPINUNLOCK(pcd->lock);
00203                 pcd->fops->suspend(pcd);
00204                 DWC_SPINLOCK(pcd->lock);
00205         }
00206 
00207         return 1;
00208 }
00209 
00216 static int32_t dwc_otg_pcd_stop_cb(void *p)
00217 {
00218         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00219         extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
00220 
00221         dwc_otg_pcd_stop(pcd);
00222         return 1;
00223 }
00224 
00228 static dwc_otg_cil_callbacks_t pcd_callbacks = {
00229         .start = dwc_otg_pcd_start_cb,
00230         .stop = dwc_otg_pcd_stop_cb,
00231         .suspend = dwc_otg_pcd_suspend_cb,
00232         .resume_wakeup = dwc_otg_pcd_resume_cb,
00233         .p = 0,                 /* Set at registration */
00234 };
00235 
00240 dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
00241                                                     uint32_t count)
00242 {
00243         return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), 
00244                                                         dma_desc_addr);
00245 }
00246 
00250 void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
00251                                 uint32_t dma_desc_addr, uint32_t count)
00252 {
00253         DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
00254                      dma_desc_addr);
00255 }
00256 
00257 #ifdef DWC_EN_ISOC
00258 
00266 void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
00267                                         dwc_ep_t * dwc_ep)
00268 {
00269 
00270         dsts_data_t dsts = {.d32 = 0 };
00271         depctl_data_t depctl = {.d32 = 0 };
00272         volatile uint32_t *addr;
00273         int i, j;
00274         uint32_t len;
00275 
00276         if (dwc_ep->is_in)
00277                 dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
00278         else
00279                 dwc_ep->desc_cnt =
00280                     dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
00281                     dwc_ep->bInterval;
00282 
00284         dwc_ep->iso_desc_addr =
00285             dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
00286                                         dwc_ep->desc_cnt * 2);
00287         if (dwc_ep->desc_addr) {
00288                 DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
00289                 return;
00290         }
00291 
00292         dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
00293 
00295         if (dwc_ep->is_in == 0) {
00296                 dev_dma_desc_sts_t sts = {.d32 = 0 };
00297                 dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
00298                 dma_addr_t dma_ad;
00299                 uint32_t data_per_desc;
00300                 dwc_otg_dev_out_ep_regs_t *out_regs =
00301                     core_if->dev_if->out_ep_regs[dwc_ep->num];
00302                 int offset;
00303 
00304                 addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
00305                 dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
00306 
00308                 dma_ad = dwc_ep->dma_addr0;
00309 
00310                 sts.b_iso_out.bs = BS_HOST_READY;
00311                 sts.b_iso_out.rxsts = 0;
00312                 sts.b_iso_out.l = 0;
00313                 sts.b_iso_out.sp = 0;
00314                 sts.b_iso_out.ioc = 0;
00315                 sts.b_iso_out.pid = 0;
00316                 sts.b_iso_out.framenum = 0;
00317 
00318                 offset = 0;
00319                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
00320                      i += dwc_ep->pkt_per_frm) {
00321 
00322                         for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
00323                                 uint32_t len = (j + 1) * dwc_ep->maxpacket;
00324                                 if (len > dwc_ep->data_per_frame)
00325                                         data_per_desc =
00326                                             dwc_ep->data_per_frame -
00327                                             j * dwc_ep->maxpacket;
00328                                 else
00329                                         data_per_desc = dwc_ep->maxpacket;
00330                                 len = data_per_desc % 4;
00331                                 if (len)
00332                                         data_per_desc += 4 - len;
00333 
00334                                 sts.b_iso_out.rxbytes = data_per_desc;
00335                                 dma_desc->buf = dma_ad;
00336                                 dma_desc->status.d32 = sts.d32;
00337 
00338                                 offset += data_per_desc;
00339                                 dma_desc++;
00340                                 dma_ad += data_per_desc;
00341                         }
00342                 }
00343 
00344                 for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
00345                         uint32_t len = (j + 1) * dwc_ep->maxpacket;
00346                         if (len > dwc_ep->data_per_frame)
00347                                 data_per_desc =
00348                                     dwc_ep->data_per_frame -
00349                                     j * dwc_ep->maxpacket;
00350                         else
00351                                 data_per_desc = dwc_ep->maxpacket;
00352                         len = data_per_desc % 4;
00353                         if (len)
00354                                 data_per_desc += 4 - len;
00355                         sts.b_iso_out.rxbytes = data_per_desc;
00356                         dma_desc->buf = dma_ad;
00357                         dma_desc->status.d32 = sts.d32;
00358 
00359                         offset += data_per_desc;
00360                         dma_desc++;
00361                         dma_ad += data_per_desc;
00362                 }
00363 
00364                 sts.b_iso_out.ioc = 1;
00365                 len = (j + 1) * dwc_ep->maxpacket;
00366                 if (len > dwc_ep->data_per_frame)
00367                         data_per_desc =
00368                             dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
00369                 else
00370                         data_per_desc = dwc_ep->maxpacket;
00371                 len = data_per_desc % 4;
00372                 if (len)
00373                         data_per_desc += 4 - len;
00374                 sts.b_iso_out.rxbytes = data_per_desc;
00375 
00376                 dma_desc->buf = dma_ad;
00377                 dma_desc->status.d32 = sts.d32;
00378                 dma_desc++;
00379 
00381                 sts.b_iso_out.ioc = 0;
00382                 dma_ad = dwc_ep->dma_addr1;
00383 
00384                 offset = 0;
00385                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
00386                      i += dwc_ep->pkt_per_frm) {
00387                         for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
00388                                 uint32_t len = (j + 1) * dwc_ep->maxpacket;
00389                                 if (len > dwc_ep->data_per_frame)
00390                                         data_per_desc =
00391                                             dwc_ep->data_per_frame -
00392                                             j * dwc_ep->maxpacket;
00393                                 else
00394                                         data_per_desc = dwc_ep->maxpacket;
00395                                 len = data_per_desc % 4;
00396                                 if (len)
00397                                         data_per_desc += 4 - len;
00398 
00399                                 data_per_desc =
00400                                     sts.b_iso_out.rxbytes = data_per_desc;
00401                                 dma_desc->buf = dma_ad;
00402                                 dma_desc->status.d32 = sts.d32;
00403 
00404                                 offset += data_per_desc;
00405                                 dma_desc++;
00406                                 dma_ad += data_per_desc;
00407                         }
00408                 }
00409                 for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
00410                         data_per_desc =
00411                             ((j + 1) * dwc_ep->maxpacket >
00412                              dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
00413                             j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00414                         data_per_desc +=
00415                             (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
00416                         sts.b_iso_out.rxbytes = data_per_desc;
00417                         dma_desc->buf = dma_ad;
00418                         dma_desc->status.d32 = sts.d32;
00419 
00420                         offset += data_per_desc;
00421                         dma_desc++;
00422                         dma_ad += data_per_desc;
00423                 }
00424 
00425                 sts.b_iso_out.ioc = 1;
00426                 sts.b_iso_out.l = 1;
00427                 data_per_desc =
00428                     ((j + 1) * dwc_ep->maxpacket >
00429                      dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
00430                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00431                 data_per_desc +=
00432                     (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
00433                 sts.b_iso_out.rxbytes = data_per_desc;
00434 
00435                 dma_desc->buf = dma_ad;
00436                 dma_desc->status.d32 = sts.d32;
00437 
00438                 dwc_ep->next_frame = 0;
00439 
00441                 DWC_WRITE_REG32(&(out_regs->doepdma),
00442                                 (uint32_t) dwc_ep->iso_dma_desc_addr);
00443 
00444         }
00446         else {
00447                 dev_dma_desc_sts_t sts = {.d32 = 0 };
00448                 dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
00449                 dma_addr_t dma_ad;
00450                 dwc_otg_dev_in_ep_regs_t *in_regs =
00451                     core_if->dev_if->in_ep_regs[dwc_ep->num];
00452                 unsigned int frmnumber;
00453                 fifosize_data_t txfifosize, rxfifosize;
00454 
00455                 txfifosize.d32 =
00456                     DWC_READ_REG32(&core_if->dev_if->
00457                                    in_ep_regs[dwc_ep->num]->dtxfsts);
00458                 rxfifosize.d32 =
00459                     DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
00460 
00461                 addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
00462 
00463                 dma_ad = dwc_ep->dma_addr0;
00464 
00465                 dsts.d32 =
00466                     DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
00467 
00468                 sts.b_iso_in.bs = BS_HOST_READY;
00469                 sts.b_iso_in.txsts = 0;
00470                 sts.b_iso_in.sp =
00471                     (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
00472                 sts.b_iso_in.ioc = 0;
00473                 sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
00474 
00475                 frmnumber = dwc_ep->next_frame;
00476 
00477                 sts.b_iso_in.framenum = frmnumber;
00478                 sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
00479                 sts.b_iso_in.l = 0;
00480 
00482                 for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
00483                         dma_desc->buf = dma_ad;
00484                         dma_desc->status.d32 = sts.d32;
00485                         dma_desc++;
00486 
00487                         dma_ad += dwc_ep->data_per_frame;
00488                         sts.b_iso_in.framenum += dwc_ep->bInterval;
00489                 }
00490 
00491                 sts.b_iso_in.ioc = 1;
00492                 dma_desc->buf = dma_ad;
00493                 dma_desc->status.d32 = sts.d32;
00494                 ++dma_desc;
00495 
00497                 sts.b_iso_in.ioc = 0;
00498                 dma_ad = dwc_ep->dma_addr1;
00499 
00500                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
00501                      i += dwc_ep->pkt_per_frm) {
00502                         dma_desc->buf = dma_ad;
00503                         dma_desc->status.d32 = sts.d32;
00504                         dma_desc++;
00505 
00506                         dma_ad += dwc_ep->data_per_frame;
00507                         sts.b_iso_in.framenum += dwc_ep->bInterval;
00508 
00509                         sts.b_iso_in.ioc = 0;
00510                 }
00511                 sts.b_iso_in.ioc = 1;
00512                 sts.b_iso_in.l = 1;
00513 
00514                 dma_desc->buf = dma_ad;
00515                 dma_desc->status.d32 = sts.d32;
00516 
00517                 dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
00518 
00520                 DWC_WRITE_REG32(&(in_regs->diepdma),
00521                                 (uint32_t) dwc_ep->iso_dma_desc_addr);
00522         }
00524         depctl.d32 = 0;
00525         depctl.b.epena = 1;
00526         depctl.b.usbactep = 1;
00527         depctl.b.cnak = 1;
00528 
00529         DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
00530         depctl.d32 = DWC_READ_REG32(addr);
00531 }
00532 
00540 void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
00541                                        dwc_ep_t * ep)
00542 {
00543         depctl_data_t depctl = {.d32 = 0 };
00544         volatile uint32_t *addr;
00545 
00546         if (ep->is_in) {
00547                 addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
00548         } else {
00549                 addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
00550         }
00551 
00552         if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
00553                 return;
00554         } else {
00555                 deptsiz_data_t deptsiz = {.d32 = 0 };
00556 
00557                 ep->xfer_len =
00558                     ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
00559                 ep->pkt_cnt =
00560                     (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
00561                 ep->xfer_count = 0;
00562                 ep->xfer_buff =
00563                     (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
00564                 ep->dma_addr =
00565                     (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
00566 
00567                 if (ep->is_in) {
00568                         /* Program the transfer size and packet count
00569                          *      as follows: xfersize = N * maxpacket +
00570                          *      short_packet pktcnt = N + (short_packet
00571                          *      exist ? 1 : 0) 
00572                          */
00573                         deptsiz.b.mc = ep->pkt_per_frm;
00574                         deptsiz.b.xfersize = ep->xfer_len;
00575                         deptsiz.b.pktcnt =
00576                             (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
00577                         DWC_WRITE_REG32(&core_if->dev_if->
00578                                         in_ep_regs[ep->num]->dieptsiz,
00579                                         deptsiz.d32);
00580 
00581                         /* Write the DMA register */
00582                         DWC_WRITE_REG32(&
00583                                         (core_if->dev_if->
00584                                          in_ep_regs[ep->num]->diepdma),
00585                                         (uint32_t) ep->dma_addr);
00586 
00587                 } else {
00588                         deptsiz.b.pktcnt =
00589                             (ep->xfer_len + (ep->maxpacket - 1)) /
00590                             ep->maxpacket;
00591                         deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
00592 
00593                         DWC_WRITE_REG32(&core_if->dev_if->
00594                                         out_ep_regs[ep->num]->doeptsiz,
00595                                         deptsiz.d32);
00596 
00597                         /* Write the DMA register */
00598                         DWC_WRITE_REG32(&
00599                                         (core_if->dev_if->
00600                                          out_ep_regs[ep->num]->doepdma),
00601                                         (uint32_t) ep->dma_addr);
00602 
00603                 }
00605                 depctl.d32 = 0;
00606                 depctl.b.epena = 1;
00607                 depctl.b.cnak = 1;
00608 
00609                 DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
00610         }
00611 }
00612 
00623 static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
00624                                           dwc_ep_t * ep)
00625 {
00626         if (core_if->dma_enable) {
00627                 if (core_if->dma_desc_enable) {
00628                         if (ep->is_in) {
00629                                 ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
00630                         } else {
00631                                 ep->desc_cnt = ep->pkt_cnt;
00632                         }
00633                         dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
00634                 } else {
00635                         if (core_if->pti_enh_enable) {
00636                                 dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
00637                         } else {
00638                                 ep->cur_pkt_addr =
00639                                     (ep->proc_buf_num) ? ep->
00640                                     xfer_buff1 : ep->xfer_buff0;
00641                                 ep->cur_pkt_dma_addr =
00642                                     (ep->proc_buf_num) ? ep->
00643                                     dma_addr1 : ep->dma_addr0;
00644                                 dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
00645                         }
00646                 }
00647         } else {
00648                 ep->cur_pkt_addr =
00649                     (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
00650                 ep->cur_pkt_dma_addr =
00651                     (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
00652                 dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
00653         }
00654 }
00655 
00664 void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
00665 {
00666         depctl_data_t depctl = {.d32 = 0 };
00667         volatile uint32_t *addr;
00668 
00669         if (ep->is_in == 1) {
00670                 addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
00671         } else {
00672                 addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
00673         }
00674 
00675         /* disable the ep */
00676         depctl.d32 = DWC_READ_REG32(addr);
00677 
00678         depctl.b.epdis = 1;
00679         depctl.b.snak = 1;
00680 
00681         DWC_WRITE_REG32(addr, depctl.d32);
00682 
00683         if (core_if->dma_desc_enable &&
00684             ep->iso_desc_addr && ep->iso_dma_desc_addr) {
00685                 dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
00686                                            ep->iso_dma_desc_addr,
00687                                            ep->desc_cnt * 2);
00688         }
00689 
00690         /* reset varibales */
00691         ep->dma_addr0 = 0;
00692         ep->dma_addr1 = 0;
00693         ep->xfer_buff0 = 0;
00694         ep->xfer_buff1 = 0;
00695         ep->data_per_frame = 0;
00696         ep->data_pattern_frame = 0;
00697         ep->sync_frame = 0;
00698         ep->buf_proc_intrvl = 0;
00699         ep->bInterval = 0;
00700         ep->proc_buf_num = 0;
00701         ep->pkt_per_frm = 0;
00702         ep->pkt_per_frm = 0;
00703         ep->desc_cnt = 0;
00704         ep->iso_desc_addr = 0;
00705         ep->iso_dma_desc_addr = 0;
00706 }
00707 
00708 int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
00709                              uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
00710                              dwc_dma_t dma1, int sync_frame, int dp_frame,
00711                              int data_per_frame, int start_frame,
00712                              int buf_proc_intrvl, void *req_handle,
00713                              int atomic_alloc)
00714 {
00715         dwc_otg_pcd_ep_t *ep;
00716         dwc_irqflags_t flags = 0;
00717         dwc_ep_t *dwc_ep;
00718         int32_t frm_data;
00719         dsts_data_t dsts;
00720         dwc_otg_core_if_t *core_if;
00721 
00722         ep = get_ep_from_handle(pcd, ep_handle);
00723 
00724         if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
00725                 DWC_WARN("bad ep\n");
00726                 return -DWC_E_INVALID;
00727         }
00728 
00729         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
00730         core_if = GET_CORE_IF(pcd);
00731         dwc_ep = &ep->dwc_ep;
00732 
00733         if (ep->iso_req_handle) {
00734                 DWC_WARN("ISO request in progress\n");
00735         }
00736 
00737         dwc_ep->dma_addr0 = dma0;
00738         dwc_ep->dma_addr1 = dma1;
00739 
00740         dwc_ep->xfer_buff0 = buf0;
00741         dwc_ep->xfer_buff1 = buf1;
00742 
00743         dwc_ep->data_per_frame = data_per_frame;
00744 
00746         dwc_ep->data_pattern_frame = dp_frame;
00747         dwc_ep->sync_frame = sync_frame;
00748 
00749         dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
00750 
00751         dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
00752 
00753         dwc_ep->proc_buf_num = 0;
00754 
00755         dwc_ep->pkt_per_frm = 0;
00756         frm_data = ep->dwc_ep.data_per_frame;
00757         while (frm_data > 0) {
00758                 dwc_ep->pkt_per_frm++;
00759                 frm_data -= ep->dwc_ep.maxpacket;
00760         }
00761 
00762         dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
00763 
00764         if (start_frame == -1) {
00765                 dwc_ep->next_frame = dsts.b.soffn + 1;
00766                 if (dwc_ep->bInterval != 1) {
00767                         dwc_ep->next_frame =
00768                             dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
00769                                                   dwc_ep->next_frame %
00770                                                   dwc_ep->bInterval);
00771                 }
00772         } else {
00773                 dwc_ep->next_frame = start_frame;
00774         }
00775 
00776         if (!core_if->pti_enh_enable) {
00777                 dwc_ep->pkt_cnt =
00778                     dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
00779                     dwc_ep->bInterval;
00780         } else {
00781                 dwc_ep->pkt_cnt =
00782                     (dwc_ep->data_per_frame *
00783                      (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
00784                      - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
00785         }
00786 
00787         if (core_if->dma_desc_enable) {
00788                 dwc_ep->desc_cnt =
00789                     dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
00790                     dwc_ep->bInterval;
00791         }
00792 
00793         if (atomic_alloc) {
00794                 dwc_ep->pkt_info =
00795                     DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
00796         } else {
00797                 dwc_ep->pkt_info =
00798                     DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
00799         }
00800         if (!dwc_ep->pkt_info) {
00801                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00802                 return -DWC_E_NO_MEMORY;
00803         }
00804         if (core_if->pti_enh_enable) {
00805                 dwc_memset(dwc_ep->pkt_info, 0,
00806                            sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
00807         }
00808 
00809         dwc_ep->cur_pkt = 0;
00810         ep->iso_req_handle = req_handle;
00811 
00812         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00813         dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
00814         return 0;
00815 }
00816 
00817 int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
00818                             void *req_handle)
00819 {
00820         dwc_irqflags_t flags = 0;
00821         dwc_otg_pcd_ep_t *ep;
00822         dwc_ep_t *dwc_ep;
00823 
00824         ep = get_ep_from_handle(pcd, ep_handle);
00825         if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
00826                 DWC_WARN("bad ep\n");
00827                 return -DWC_E_INVALID;
00828         }
00829         dwc_ep = &ep->dwc_ep;
00830 
00831         dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
00832 
00833         DWC_FREE(dwc_ep->pkt_info);
00834         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
00835         if (ep->iso_req_handle != req_handle) {
00836                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00837                 return -DWC_E_INVALID;
00838         }
00839 
00840         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00841 
00842         ep->iso_req_handle = 0;
00843         return 0;
00844 }
00845 
00853 void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
00854                              void *req_handle)
00855 {
00856         int i;
00857         dwc_ep_t *dwc_ep;
00858 
00859         dwc_ep = &ep->dwc_ep;
00860 
00861         DWC_SPINUNLOCK(ep->pcd->lock);
00862         pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
00863                                  dwc_ep->proc_buf_num ^ 0x1);
00864         DWC_SPINLOCK(ep->pcd->lock);
00865 
00866         for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
00867                 dwc_ep->pkt_info[i].status = 0;
00868                 dwc_ep->pkt_info[i].offset = 0;
00869                 dwc_ep->pkt_info[i].length = 0;
00870         }
00871 }
00872 
00873 int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
00874                                      void *iso_req_handle)
00875 {
00876         dwc_otg_pcd_ep_t *ep;
00877         dwc_ep_t *dwc_ep;
00878 
00879         ep = get_ep_from_handle(pcd, ep_handle);
00880         if (!ep->desc || ep->dwc_ep.num == 0) {
00881                 DWC_WARN("bad ep\n");
00882                 return -DWC_E_INVALID;
00883         }
00884         dwc_ep = &ep->dwc_ep;
00885 
00886         return dwc_ep->pkt_cnt;
00887 }
00888 
00889 void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
00890                                        void *iso_req_handle, int packet,
00891                                        int *status, int *actual, int *offset)
00892 {
00893         dwc_otg_pcd_ep_t *ep;
00894         dwc_ep_t *dwc_ep;
00895 
00896         ep = get_ep_from_handle(pcd, ep_handle);
00897         if (!ep)
00898                 DWC_WARN("bad ep\n");
00899 
00900         dwc_ep = &ep->dwc_ep;
00901 
00902         *status = dwc_ep->pkt_info[packet].status;
00903         *actual = dwc_ep->pkt_info[packet].length;
00904         *offset = dwc_ep->pkt_info[packet].offset;
00905 }
00906 
00907 #endif /* DWC_EN_ISOC */
00908 
00909 static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
00910                                 uint32_t is_in, uint32_t ep_num)
00911 {
00912         /* Init EP structure */
00913         pcd_ep->desc = 0;
00914         pcd_ep->pcd = pcd;
00915         pcd_ep->stopped = 1;
00916         pcd_ep->queue_sof = 0;
00917 
00918         /* Init DWC ep structure */
00919         pcd_ep->dwc_ep.is_in = is_in;
00920         pcd_ep->dwc_ep.num = ep_num;
00921         pcd_ep->dwc_ep.active = 0;
00922         pcd_ep->dwc_ep.tx_fifo_num = 0;
00923         /* Control until ep is actvated */
00924         pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
00925         pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
00926         pcd_ep->dwc_ep.dma_addr = 0;
00927         pcd_ep->dwc_ep.start_xfer_buff = 0;
00928         pcd_ep->dwc_ep.xfer_buff = 0;
00929         pcd_ep->dwc_ep.xfer_len = 0;
00930         pcd_ep->dwc_ep.xfer_count = 0;
00931         pcd_ep->dwc_ep.sent_zlp = 0;
00932         pcd_ep->dwc_ep.total_len = 0;
00933         pcd_ep->dwc_ep.desc_addr = 0;
00934         pcd_ep->dwc_ep.dma_desc_addr = 0;
00935         DWC_CIRCLEQ_INIT(&pcd_ep->queue);
00936 }
00937 
00941 static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
00942 {
00943         int i;
00944         uint32_t hwcfg1;
00945         dwc_otg_pcd_ep_t *ep;
00946         int in_ep_cntr, out_ep_cntr;
00947         uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
00948         uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
00949 
00953         ep = &pcd->ep0;
00954         dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
00955 
00956         in_ep_cntr = 0;
00957         hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
00958         for (i = 1; in_ep_cntr < num_in_eps; i++) {
00959                 if ((hwcfg1 & 0x1) == 0) {
00960                         dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
00961                         in_ep_cntr++;
00967                         dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
00968 
00969                         DWC_CIRCLEQ_INIT(&ep->queue);
00970                 }
00971                 hwcfg1 >>= 2;
00972         }
00973 
00974         out_ep_cntr = 0;
00975         hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
00976         for (i = 1; out_ep_cntr < num_out_eps; i++) {
00977                 if ((hwcfg1 & 0x1) == 0) {
00978                         dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
00979                         out_ep_cntr++;
00985                         dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
00986                         DWC_CIRCLEQ_INIT(&ep->queue);
00987                 }
00988                 hwcfg1 >>= 2;
00989         }
00990 
00991         pcd->ep0state = EP0_DISCONNECT;
00992         pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
00993         pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
00994 }
00995 
01000 static void srp_timeout(void *ptr)
01001 {
01002         gotgctl_data_t gotgctl;
01003         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
01004         volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
01005 
01006         gotgctl.d32 = DWC_READ_REG32(addr);
01007 
01008         core_if->srp_timer_started = 0;
01009         
01010         if (core_if->adp_enable) {
01011                 if (gotgctl.b.bsesvld == 0) {
01012                         gpwrdn_data_t gpwrdn = {.d32 = 0 };
01013                         DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
01014                         /* Power off the core */
01015                         if (core_if->power_down == 2) {
01016                                 gpwrdn.b.pwrdnswtch = 1;
01017                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
01018                                         gpwrdn, gpwrdn.d32, 0);
01019                         }
01020 
01021                         gpwrdn.d32 = 0;
01022                         gpwrdn.b.pmuintsel = 1;
01023                         gpwrdn.b.pmuactv = 1;
01024                         DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
01025                         dwc_otg_adp_probe_start(core_if);
01026                 } else {
01027                         DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
01028                         core_if->op_state = B_PERIPHERAL;
01029                         dwc_otg_core_init(core_if);
01030                         dwc_otg_enable_global_interrupts(core_if);
01031                         cil_pcd_start(core_if);
01032                 }
01033         }
01034 
01035         if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
01036             (core_if->core_params->i2c_enable)) {
01037                 DWC_PRINTF("SRP Timeout\n");
01038 
01039                 if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
01040                         if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
01041                                 core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
01042                         }
01043 
01044                         /* Clear Session Request */
01045                         gotgctl.d32 = 0;
01046                         gotgctl.b.sesreq = 1;
01047                         DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
01048                                          gotgctl.d32, 0);
01049 
01050                         core_if->srp_success = 0;
01051                 } else {
01052                         __DWC_ERROR("Device not connected/responding\n");
01053                         gotgctl.b.sesreq = 0;
01054                         DWC_WRITE_REG32(addr, gotgctl.d32);
01055                 }
01056         } else if (gotgctl.b.sesreq) {
01057                 DWC_PRINTF("SRP Timeout\n");
01058 
01059                 __DWC_ERROR("Device not connected/responding\n");
01060                 gotgctl.b.sesreq = 0;
01061                 DWC_WRITE_REG32(addr, gotgctl.d32);
01062         } else {
01063                 DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
01064         }
01065 }
01066 
01071 extern void start_next_request(dwc_otg_pcd_ep_t * ep);
01072 
01073 static void start_xfer_tasklet_func(void *data)
01074 {
01075         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
01076         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01077 
01078         int i;
01079         depctl_data_t diepctl;
01080 
01081         DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
01082 
01083         diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
01084 
01085         if (pcd->ep0.queue_sof) {
01086                 pcd->ep0.queue_sof = 0;
01087                 start_next_request(&pcd->ep0);
01088                 // break;
01089         }
01090 
01091         for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
01092                 depctl_data_t diepctl;
01093                 diepctl.d32 =
01094                     DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
01095 
01096                 if (pcd->in_ep[i].queue_sof) {
01097                         pcd->in_ep[i].queue_sof = 0;
01098                         start_next_request(&pcd->in_ep[i]);
01099                         // break;
01100                 }
01101         }
01102 
01103         return;
01104 }
01105 
01110 dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
01111 {
01112         dwc_otg_pcd_t *pcd = NULL;
01113         dwc_otg_dev_if_t *dev_if;
01114         int i;
01115 
01116         /*
01117          * Allocate PCD structure
01118          */
01119         pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
01120 
01121         if (pcd == NULL) {
01122                 return NULL;
01123         }
01124 
01125         pcd->lock = DWC_SPINLOCK_ALLOC();
01126         if (!pcd->lock) {
01127                 DWC_ERROR("Could not allocate lock for pcd");
01128                 DWC_FREE(pcd);
01129                 return NULL;
01130         }
01131         /* Set core_if's lock pointer to hcd->lock */
01132         core_if->lock = pcd->lock;
01133         pcd->core_if = core_if;
01134 
01135         dev_if = core_if->dev_if;
01136         dev_if->isoc_ep = NULL;
01137 
01138         if (core_if->hwcfg4.b.ded_fifo_en) {
01139                 DWC_PRINTF("Dedicated Tx FIFOs mode\n");
01140         } else {
01141                 DWC_PRINTF("Shared Tx FIFO mode\n");
01142         }
01143 
01144         /*
01145          * Initialized the Core for Device mode here if there is nod ADP support. 
01146          * Otherwise it will be done later in dwc_otg_adp_start routine.
01147          */                                                                                                                                                              
01148         if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
01149                 dwc_otg_core_dev_init(core_if);
01150         }
01151 
01152         /*
01153          * Register the PCD Callbacks.
01154          */
01155         dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
01156 
01157         /*
01158          * Initialize the DMA buffer for SETUP packets
01159          */
01160         if (GET_CORE_IF(pcd)->dma_enable) {
01161                 pcd->setup_pkt =
01162                     DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
01163                                   &pcd->setup_pkt_dma_handle);
01164                 if (pcd->setup_pkt == NULL) {
01165                         DWC_FREE(pcd);
01166                         return NULL;
01167                 }
01168 
01169                 pcd->status_buf =
01170                     DWC_DMA_ALLOC(sizeof(uint16_t),
01171                                   &pcd->status_buf_dma_handle);
01172                 if (pcd->status_buf == NULL) {
01173                         DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
01174                                      pcd->setup_pkt, pcd->setup_pkt_dma_handle);
01175                         DWC_FREE(pcd);
01176                         return NULL;
01177                 }
01178 
01179                 if (GET_CORE_IF(pcd)->dma_desc_enable) {
01180                         dev_if->setup_desc_addr[0] =
01181                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01182                                                         dma_setup_desc_addr[0],
01183                                                         1);
01184                         dev_if->setup_desc_addr[1] =
01185                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01186                                                         dma_setup_desc_addr[1],
01187                                                         1);
01188                         dev_if->in_desc_addr =
01189                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01190                                                         dma_in_desc_addr, 1);
01191                         dev_if->out_desc_addr =
01192                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01193                                                         dma_out_desc_addr, 1);
01194 
01195                         if (dev_if->setup_desc_addr[0] == 0
01196                             || dev_if->setup_desc_addr[1] == 0
01197                             || dev_if->in_desc_addr == 0
01198                             || dev_if->out_desc_addr == 0) {
01199 
01200                                 if (dev_if->out_desc_addr)
01201                                         dwc_otg_ep_free_desc_chain(dev_if->
01202                                                                    out_desc_addr,
01203                                                                    dev_if->
01204                                                                    dma_out_desc_addr,
01205                                                                    1);
01206                                 if (dev_if->in_desc_addr)
01207                                         dwc_otg_ep_free_desc_chain(dev_if->
01208                                                                    in_desc_addr,
01209                                                                    dev_if->
01210                                                                    dma_in_desc_addr,
01211                                                                    1);
01212                                 if (dev_if->setup_desc_addr[1])
01213                                         dwc_otg_ep_free_desc_chain(dev_if->
01214                                                                    setup_desc_addr
01215                                                                    [1],
01216                                                                    dev_if->
01217                                                                    dma_setup_desc_addr
01218                                                                    [1], 1);
01219                                 if (dev_if->setup_desc_addr[0])
01220                                         dwc_otg_ep_free_desc_chain(dev_if->
01221                                                                    setup_desc_addr
01222                                                                    [0],
01223                                                                    dev_if->
01224                                                                    dma_setup_desc_addr
01225                                                                    [0], 1);
01226 
01227                                 DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
01228                                              pcd->setup_pkt,
01229                                              pcd->setup_pkt_dma_handle);
01230                                 DWC_DMA_FREE(sizeof(*pcd->status_buf),
01231                                              pcd->status_buf,
01232                                              pcd->status_buf_dma_handle);
01233 
01234                                 DWC_FREE(pcd);
01235 
01236                                 return NULL;
01237                         }
01238                 }
01239         } else {
01240                 pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
01241                 if (pcd->setup_pkt == NULL) {
01242                         DWC_FREE(pcd);
01243                         return NULL;
01244                 }
01245 
01246                 pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
01247                 if (pcd->status_buf == NULL) {
01248                         DWC_FREE(pcd->setup_pkt);
01249                         DWC_FREE(pcd);
01250                         return NULL;
01251                 }
01252         }
01253 
01254         dwc_otg_pcd_reinit(pcd);
01255 
01256         /* Allocate the cfi object for the PCD */
01257 #ifdef DWC_UTE_CFI
01258         pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
01259         if (NULL == pcd->cfi)
01260                 goto fail;
01261         if (init_cfi(pcd->cfi)) {
01262                 CFI_INFO("%s: Failed to init the CFI object\n", __func__);
01263                 goto fail;
01264         }
01265 #endif
01266 
01267         /* Initialize tasklets */
01268         pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
01269                                                  start_xfer_tasklet_func, pcd);
01270         pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
01271                                                 do_test_mode, pcd);
01272 
01273         /* Initialize SRP timer */
01274         core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
01275         
01276         if (core_if->core_params->dev_out_nak) {
01281                 for(i = 0; i < MAX_EPS_CHANNELS; i++) {
01282                         pcd->core_if->ep_xfer_timer[i] =
01283                                 DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
01284                                 &pcd->core_if->ep_xfer_info[i]);
01285                 }
01286         }
01287         
01288         return pcd;
01289 #ifdef DWC_UTE_CFI
01290 fail:
01291 #endif
01292         if (pcd->setup_pkt)
01293                 DWC_FREE(pcd->setup_pkt);
01294         if (pcd->status_buf)
01295                 DWC_FREE(pcd->status_buf);
01296 #ifdef DWC_UTE_CFI
01297         if (pcd->cfi)
01298                 DWC_FREE(pcd->cfi);
01299 #endif
01300         if (pcd)
01301                 DWC_FREE(pcd);
01302         return NULL;
01303 
01304 }
01305 
01309 void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
01310 {
01311         dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
01312         int i;
01313         if (pcd->core_if->core_params->dev_out_nak) {
01314                 for (i = 0; i < MAX_EPS_CHANNELS; i++) {
01315                         DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
01316                         pcd->core_if->ep_xfer_info[i].state = 0;
01317                 }
01318         }
01319 
01320         if (GET_CORE_IF(pcd)->dma_enable) {
01321                 DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
01322                              pcd->setup_pkt_dma_handle);
01323                 DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
01324                              pcd->status_buf_dma_handle);
01325                 if (GET_CORE_IF(pcd)->dma_desc_enable) {
01326                         dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
01327                                                    dev_if->dma_setup_desc_addr
01328                                                    [0], 1);
01329                         dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
01330                                                    dev_if->dma_setup_desc_addr
01331                                                    [1], 1);
01332                         dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
01333                                                    dev_if->dma_in_desc_addr, 1);
01334                         dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
01335                                                    dev_if->dma_out_desc_addr,
01336                                                    1);
01337                 }
01338         } else {
01339                 DWC_FREE(pcd->setup_pkt);
01340                 DWC_FREE(pcd->status_buf);
01341         }
01342         DWC_SPINLOCK_FREE(pcd->lock);
01343         /* Set core_if's lock pointer to NULL */
01344         pcd->core_if->lock = NULL;
01345 
01346         DWC_TASK_FREE(pcd->start_xfer_tasklet);
01347         DWC_TASK_FREE(pcd->test_mode_tasklet);
01348         if (pcd->core_if->core_params->dev_out_nak) {
01349                 for (i = 0; i < MAX_EPS_CHANNELS; i++) {
01350                         if (pcd->core_if->ep_xfer_timer[i]) {
01351                                         DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
01352                         }
01353                 }
01354         }
01355 
01356 /* Release the CFI object's dynamic memory */
01357 #ifdef DWC_UTE_CFI
01358         if (pcd->cfi->ops.release) {
01359                 pcd->cfi->ops.release(pcd->cfi);
01360         }
01361 #endif
01362 
01363         DWC_FREE(pcd);
01364 }
01365 
01369 uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
01370 {
01371         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01372 
01373         if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
01374             ((core_if->hwcfg2.b.hs_phy_type == 2) &&
01375              (core_if->hwcfg2.b.fs_phy_type == 1) &&
01376              (core_if->core_params->ulpi_fs_ls))) {
01377                 return 0;
01378         }
01379 
01380         return 1;
01381 }
01382 
01386 uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
01387 {
01388         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01389         gusbcfg_data_t usbcfg = {.d32 = 0 };
01390 
01391         usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
01392         if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
01393                 return 0;
01394         }
01395 
01396         return 1;
01397 }
01398 
01403 static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
01404 {
01405         uint32_t TxMsk = 1;
01406         int i;
01407 
01408         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
01409                 if ((TxMsk & core_if->tx_msk) == 0) {
01410                         core_if->tx_msk |= TxMsk;
01411                         return i + 1;
01412                 }
01413                 TxMsk <<= 1;
01414         }
01415         return 0;
01416 }
01417 
01422 static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
01423 {
01424         uint32_t PerTxMsk = 1;
01425         int i;
01426         for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
01427                 if ((PerTxMsk & core_if->p_tx_msk) == 0) {
01428                         core_if->p_tx_msk |= PerTxMsk;
01429                         return i + 1;
01430                 }
01431                 PerTxMsk <<= 1;
01432         }
01433         return 0;
01434 }
01435 
01440 static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
01441                                   uint32_t fifo_num)
01442 {
01443         core_if->p_tx_msk =
01444             (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
01445 }
01446 
01451 static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
01452 {
01453         core_if->tx_msk =
01454             (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
01455 }
01456 
01461 int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
01462                           const uint8_t * ep_desc, void *usb_ep)
01463 {
01464         int num, dir;
01465         dwc_otg_pcd_ep_t *ep = NULL;
01466         const usb_endpoint_descriptor_t *desc;
01467         dwc_irqflags_t flags;
01468         fifosize_data_t dptxfsiz = {.d32 = 0 };
01469         gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
01470         gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
01471         int retval = 0;
01472         int i, epcount;
01473 
01474         desc = (const usb_endpoint_descriptor_t *)ep_desc;
01475 
01476         if (!desc) {
01477                 pcd->ep0.priv = usb_ep;
01478                 ep = &pcd->ep0;
01479                 retval = -DWC_E_INVALID;
01480                 goto out;
01481         }
01482 
01483         num = UE_GET_ADDR(desc->bEndpointAddress);
01484         dir = UE_GET_DIR(desc->bEndpointAddress);
01485 
01486         if (!desc->wMaxPacketSize) {
01487                 DWC_WARN("bad maxpacketsize\n");
01488                 retval = -DWC_E_INVALID;
01489                 goto out;
01490         }
01491 
01492         if (dir == UE_DIR_IN) {
01493                 epcount = pcd->core_if->dev_if->num_in_eps;
01494                 for (i = 0; i < epcount; i++) {
01495                         if (num == pcd->in_ep[i].dwc_ep.num) {
01496                                 ep = &pcd->in_ep[i];
01497                                 break;
01498                         }
01499                 }
01500         } else {
01501                 epcount = pcd->core_if->dev_if->num_out_eps;
01502                 for (i = 0; i < epcount; i++) {
01503                         if (num == pcd->out_ep[i].dwc_ep.num) {
01504                                 ep = &pcd->out_ep[i];
01505                                 break;
01506                         }
01507                 }
01508         }
01509 
01510         if (!ep) {
01511                 DWC_WARN("bad address\n");
01512                 retval = -DWC_E_INVALID;
01513                 goto out;
01514         }
01515 
01516         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01517 
01518         ep->desc = desc;
01519         ep->priv = usb_ep;
01520 
01521         /*
01522          * Activate the EP
01523          */
01524         ep->stopped = 0;
01525 
01526         ep->dwc_ep.is_in = (dir == UE_DIR_IN);
01527         ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
01528 
01529         ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
01530 
01531         if (ep->dwc_ep.is_in) {
01532                 if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
01533                         ep->dwc_ep.tx_fifo_num = 0;
01534 
01535                         if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
01536                                 /*
01537                                  * if ISOC EP then assign a Periodic Tx FIFO.
01538                                  */
01539                                 ep->dwc_ep.tx_fifo_num =
01540                                     assign_perio_tx_fifo(GET_CORE_IF(pcd));
01541                         }
01542                 } else {
01543                         /*
01544                          * if Dedicated FIFOs mode is on then assign a Tx FIFO.
01545                          */
01546                         ep->dwc_ep.tx_fifo_num =
01547                             assign_tx_fifo(GET_CORE_IF(pcd));
01548                 }
01549 
01550                 /* Calculating EP info controller base address */
01551                 if (ep->dwc_ep.tx_fifo_num && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
01552                         gdfifocfg.d32 =
01553                             DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
01554                                            gdfifocfg);
01555                         gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
01556                         dptxfsiz.d32 =
01557                             (DWC_READ_REG32
01558                              (&GET_CORE_IF(pcd)->
01559                               core_global_regs->dtxfsiz[ep->dwc_ep.
01560                                                         tx_fifo_num-1]) >> 16);
01561                         gdfifocfg.b.epinfobase =
01562                             gdfifocfgbase.d32 + dptxfsiz.d32;
01563                         DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->
01564                                         gdfifocfg, gdfifocfg.d32);
01565                 }
01566         }
01567         /* Set initial data PID. */
01568         if (ep->dwc_ep.type == UE_BULK) {
01569                 ep->dwc_ep.data_pid_start = 0;
01570         }
01571 
01572         /* Alloc DMA Descriptors */
01573         if (GET_CORE_IF(pcd)->dma_desc_enable) {
01574 #ifndef DWC_UTE_PER_IO
01575                 if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
01576 #endif
01577                         ep->dwc_ep.desc_addr =
01578                             dwc_otg_ep_alloc_desc_chain(&ep->
01579                                                         dwc_ep.dma_desc_addr,
01580                                                         MAX_DMA_DESC_CNT);
01581                         if (!ep->dwc_ep.desc_addr) {
01582                                 DWC_WARN("%s, can't allocate DMA descriptor\n",
01583                                          __func__);
01584                                 retval = -DWC_E_SHUTDOWN;
01585                                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01586                                 goto out;
01587                         }
01588 #ifndef DWC_UTE_PER_IO
01589                 }
01590 #endif
01591         }
01592 
01593         DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
01594                     (ep->dwc_ep.is_in ? "IN" : "OUT"),
01595                     ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
01596 #ifdef DWC_UTE_PER_IO
01597         ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
01598 #endif
01599         if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
01600                 ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
01601                 ep->dwc_ep.frame_num = 0xFFFFFFFF;
01602         }               
01603 
01604         dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
01605 
01606 #ifdef DWC_UTE_CFI
01607         if (pcd->cfi->ops.ep_enable) {
01608                 pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
01609         }
01610 #endif
01611 
01612         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01613 
01614 out:
01615         return retval;
01616 }
01617 
01622 int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
01623 {
01624         dwc_otg_pcd_ep_t *ep;
01625         dwc_irqflags_t flags;
01626         dwc_otg_dev_dma_desc_t *desc_addr;
01627         dwc_dma_t dma_desc_addr;
01628         gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
01629         gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
01630         fifosize_data_t dptxfsiz = {.d32 = 0 };
01631 
01632         ep = get_ep_from_handle(pcd, ep_handle);
01633 
01634         if (!ep || !ep->desc) {
01635                 DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
01636                 return -DWC_E_INVALID;
01637         }
01638 
01639         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01640 
01641         dwc_otg_request_nuke(ep);
01642 
01643         dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
01644         if (pcd->core_if->core_params->dev_out_nak)
01645         {
01646                 DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
01647                 pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
01648         }
01649         ep->desc = NULL;
01650         ep->stopped = 1;
01651 
01652         gdfifocfg.d32 =
01653             DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
01654         gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
01655 
01656         if (ep->dwc_ep.is_in) {
01657                 if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
01658                         /* Flush the Tx FIFO */
01659                         dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
01660                 }
01661                 release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
01662                 release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
01663                 if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
01664                         /* Decreasing EPinfo Base Addr */
01665                         dptxfsiz.d32 =
01666                             (DWC_READ_REG32
01667                              (&GET_CORE_IF(pcd)->
01668                                 core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
01669                         gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
01670                         DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
01671                                         gdfifocfg.d32);
01672                 }
01673         }
01674 
01675         /* Free DMA Descriptors */
01676         if (GET_CORE_IF(pcd)->dma_desc_enable) {
01677                 if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
01678                         desc_addr = ep->dwc_ep.desc_addr;
01679                         dma_desc_addr = ep->dwc_ep.dma_desc_addr;
01680 
01681                         /* Cannot call dma_free_coherent() with IRQs disabled */
01682                         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01683                         dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
01684                                                    MAX_DMA_DESC_CNT);
01685 
01686                         goto out_unlocked;
01687                 }
01688         }
01689         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01690 
01691 out_unlocked:
01692         DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
01693                     ep->dwc_ep.is_in ? "IN" : "OUT");
01694         return 0;
01695 
01696 }
01697 
01698 /******************************************************************************/
01699 #ifdef DWC_UTE_PER_IO
01700 
01705 void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
01706 {
01707         DWC_FREE(req->ext_req.per_io_frame_descs);
01708         DWC_FREE(req);
01709 }
01710 
01715 int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
01716                                         dwc_otg_pcd_ep_t * ep)
01717 {
01718         int i;
01719         dwc_otg_pcd_request_t *req = NULL;
01720         dwc_ep_t *dwcep = NULL;
01721         struct dwc_iso_xreq_port *ereq = NULL;
01722         struct dwc_iso_pkt_desc_port *ddesc_iso;
01723         uint16_t nat;
01724         depctl_data_t diepctl;
01725 
01726         dwcep = &ep->dwc_ep;
01727 
01728         if (dwcep->xiso_active_xfers > 0) {
01729 #if 0   //Disable this to decrease s/w overhead that is crucial for Isoc transfers
01730                 DWC_WARN("There are currently active transfers for EP%d \
01731                                 (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, 
01732                                 dwcep->xiso_queued_xfers);
01733 #endif
01734                 return 0;
01735         }
01736 
01737         nat = UGETW(ep->desc->wMaxPacketSize);
01738         nat = (nat >> 11) & 0x03;
01739 
01740         if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
01741                 req = DWC_CIRCLEQ_FIRST(&ep->queue);
01742                 ereq = &req->ext_req;
01743                 ep->stopped = 0;
01744 
01745                 /* Get the frame number */
01746                 dwcep->xiso_frame_num =
01747                     dwc_otg_get_frame_number(GET_CORE_IF(pcd));
01748                 DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
01749 
01750                 ddesc_iso = ereq->per_io_frame_descs;
01751 
01752                 if (dwcep->is_in) {
01753                         /* Setup DMA Descriptor chain for IN Isoc request */
01754                         for (i = 0; i < ereq->pio_pkt_count; i++) {
01755                                 //if ((i % (nat + 1)) == 0)
01756                                 if ( i > 0 )
01757                                         dwcep->xiso_frame_num = (dwcep->xiso_bInterval +
01758                                                                                 dwcep->xiso_frame_num) & 0x3FFF;
01759                                 dwcep->desc_addr[i].buf =
01760                                     req->dma + ddesc_iso[i].offset;
01761                                 dwcep->desc_addr[i].status.b_iso_in.txbytes =
01762                                     ddesc_iso[i].length;
01763                                 dwcep->desc_addr[i].status.b_iso_in.framenum =
01764                                     dwcep->xiso_frame_num;
01765                                 dwcep->desc_addr[i].status.b_iso_in.bs =
01766                                     BS_HOST_READY;
01767                                 dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
01768                                 dwcep->desc_addr[i].status.b_iso_in.sp =
01769                                     (ddesc_iso[i].length %
01770                                      dwcep->maxpacket) ? 1 : 0;
01771                                 dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
01772                                 dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
01773                                 dwcep->desc_addr[i].status.b_iso_in.l = 0;
01774 
01775                                 /* Process the last descriptor */
01776                                 if (i == ereq->pio_pkt_count - 1) {
01777                                         dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
01778                                         dwcep->desc_addr[i].status.b_iso_in.l = 1;
01779                                 }
01780                         }
01781 
01782                         /* Setup and start the transfer for this endpoint */
01783                         dwcep->xiso_active_xfers++;
01784                         DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
01785                                         in_ep_regs[dwcep->num]->diepdma,
01786                                         dwcep->dma_desc_addr);
01787                         diepctl.d32 = 0;
01788                         diepctl.b.epena = 1;
01789                         diepctl.b.cnak = 1;
01790                         DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
01791                                          in_ep_regs[dwcep->num]->diepctl, 0,
01792                                          diepctl.d32);
01793                 } else {
01794                         /* Setup DMA Descriptor chain for OUT Isoc request */
01795                         for (i = 0; i < ereq->pio_pkt_count; i++) {
01796                                 //if ((i % (nat + 1)) == 0)
01797                                 dwcep->xiso_frame_num = (dwcep->xiso_bInterval + 
01798                                                                                 dwcep->xiso_frame_num) & 0x3FFF;
01799                                 dwcep->desc_addr[i].buf =
01800                                     req->dma + ddesc_iso[i].offset;
01801                                 dwcep->desc_addr[i].status.b_iso_out.rxbytes =
01802                                     ddesc_iso[i].length;
01803                                 dwcep->desc_addr[i].status.b_iso_out.framenum =
01804                                     dwcep->xiso_frame_num;
01805                                 dwcep->desc_addr[i].status.b_iso_out.bs =
01806                                     BS_HOST_READY;
01807                                 dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
01808                                 dwcep->desc_addr[i].status.b_iso_out.sp =
01809                                     (ddesc_iso[i].length %
01810                                      dwcep->maxpacket) ? 1 : 0;
01811                                 dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
01812                                 dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
01813                                 dwcep->desc_addr[i].status.b_iso_out.l = 0;
01814                                 
01815                                 /* Process the last descriptor */
01816                                 if (i == ereq->pio_pkt_count - 1) {
01817                                         dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
01818                                         dwcep->desc_addr[i].status.b_iso_out.l = 1;
01819                                 }                       
01820                         }
01821                         
01822                         /* Setup and start the transfer for this endpoint */
01823                         dwcep->xiso_active_xfers++;
01824                         DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
01825                                         out_ep_regs[dwcep->num]->doepdma,
01826                                         dwcep->dma_desc_addr);
01827                         diepctl.d32 = 0;
01828                         diepctl.b.epena = 1;
01829                         diepctl.b.cnak = 1;
01830                         DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
01831                                          out_ep_regs[dwcep->num]->doepctl, 0,
01832                                          diepctl.d32);
01833                 }
01834 
01835         } else {
01836                 ep->stopped = 1;
01837         }
01838 
01839         return 0;
01840 }
01841 
01845 void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
01846 {
01847         dwc_otg_pcd_request_t *req = NULL;
01848         struct dwc_iso_xreq_port *ereq = NULL;
01849         struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
01850         dwc_ep_t *dwcep = NULL;
01851         int i;
01852 
01853         //DWC_DEBUG();
01854         dwcep = &ep->dwc_ep;
01855 
01856         /* Get the first pending request from the queue */
01857         if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
01858                 req = DWC_CIRCLEQ_FIRST(&ep->queue);
01859                 if (!req) {
01860                         DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
01861                         return;
01862                 }
01863                 dwcep->xiso_active_xfers--;
01864                 dwcep->xiso_queued_xfers--;
01865                 /* Remove this request from the queue */
01866                 DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
01867         } else {
01868                 DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
01869                 return;
01870         }
01871 
01872         ep->stopped = 1;
01873         ereq = &req->ext_req;
01874         ddesc_iso = ereq->per_io_frame_descs;
01875 
01876         if (dwcep->xiso_active_xfers < 0) {
01877                 DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
01878                          dwcep->xiso_active_xfers);
01879         }
01880 
01881         /* Fill the Isoc descs of portable extended req from dma descriptors */
01882         for (i = 0; i < ereq->pio_pkt_count; i++) {
01883                 if (dwcep->is_in) {     /* IN endpoints */
01884                         ddesc_iso[i].actual_length = ddesc_iso[i].length -
01885                             dwcep->desc_addr[i].status.b_iso_in.txbytes;
01886                         ddesc_iso[i].status =
01887                             dwcep->desc_addr[i].status.b_iso_in.txsts;
01888                 } else {        /* OUT endpoints */
01889                         ddesc_iso[i].actual_length = ddesc_iso[i].length -
01890                             dwcep->desc_addr[i].status.b_iso_out.rxbytes;
01891                         ddesc_iso[i].status =
01892                             dwcep->desc_addr[i].status.b_iso_out.rxsts;
01893                 }
01894         }
01895 
01896         DWC_SPINUNLOCK(ep->pcd->lock);
01897 
01898         /* Call the completion function in the non-portable logic */
01899         ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
01900                                       &req->ext_req);
01901 
01902         DWC_SPINLOCK(ep->pcd->lock);
01903 
01904         /* Free the request - specific freeing needed for extended request object */
01905         dwc_pcd_xiso_ereq_free(ep, req);
01906 
01907         /* Start the next request */
01908         dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
01909 
01910         return;
01911 }
01912 
01917 static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
01918                                              void *ereq_nonport,
01919                                              int atomic_alloc)
01920 {
01921         struct dwc_iso_xreq_port *ereq = NULL;
01922         struct dwc_iso_xreq_port *req_mapped = NULL;
01923         struct dwc_iso_pkt_desc_port *ipds = NULL;      /* To be created in this function */
01924         uint32_t pkt_count;
01925         int i;
01926 
01927         ereq = &req->ext_req;
01928         req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
01929         pkt_count = req_mapped->pio_pkt_count;
01930 
01931         /* Create the isoc descs */
01932         if (atomic_alloc) {
01933                 ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
01934         } else {
01935                 ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
01936         }
01937 
01938         if (!ipds) {
01939                 DWC_ERROR("Failed to allocate isoc descriptors");
01940                 return -DWC_E_NO_MEMORY;
01941         }
01942 
01943         /* Initialize the extended request fields */
01944         ereq->per_io_frame_descs = ipds;
01945         ereq->error_count = 0;
01946         ereq->pio_alloc_pkt_count = pkt_count;
01947         ereq->pio_pkt_count = pkt_count;
01948         ereq->tr_sub_flags = req_mapped->tr_sub_flags;
01949 
01950         /* Init the Isoc descriptors */
01951         for (i = 0; i < pkt_count; i++) {
01952                 ipds[i].length = req_mapped->per_io_frame_descs[i].length;
01953                 ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
01954                 ipds[i].status = req_mapped->per_io_frame_descs[i].status;      /* 0 */
01955                 ipds[i].actual_length =
01956                     req_mapped->per_io_frame_descs[i].actual_length;
01957         }
01958 
01959         return 0;
01960 }
01961 
01962 static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
01963 {
01964         struct dwc_iso_pkt_desc_port *xfd = NULL;
01965         int i;
01966 
01967         DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
01968         DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
01969         DWC_DEBUG("error_count=%d", ereq->error_count);
01970         DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
01971         DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
01972         DWC_DEBUG("res=%d", ereq->res);
01973 
01974         for (i = 0; i < ereq->pio_pkt_count; i++) {
01975                 xfd = &ereq->per_io_frame_descs[0];
01976                 DWC_DEBUG("FD #%d", i);
01977 
01978                 DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
01979                 DWC_DEBUG("xfd->length=%d", xfd->length);
01980                 DWC_DEBUG("xfd->offset=%d", xfd->offset);
01981                 DWC_DEBUG("xfd->status=%d", xfd->status);
01982         }
01983 }
01984 
01988 int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
01989                               uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
01990                               int zero, void *req_handle, int atomic_alloc,
01991                               void *ereq_nonport)
01992 {
01993         dwc_otg_pcd_request_t *req = NULL;
01994         dwc_otg_pcd_ep_t *ep;
01995         dwc_irqflags_t flags;
01996         int res;
01997 
01998         ep = get_ep_from_handle(pcd, ep_handle);
01999         if (!ep) {
02000                 DWC_WARN("bad ep\n");
02001                 return -DWC_E_INVALID;
02002         }
02003 
02004         /* We support this extension only for DDMA mode */
02005         if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
02006                 if (!GET_CORE_IF(pcd)->dma_desc_enable)
02007                         return -DWC_E_INVALID;
02008 
02009         /* Create a dwc_otg_pcd_request_t object */
02010         if (atomic_alloc) {
02011                 req = DWC_ALLOC_ATOMIC(sizeof(*req));
02012         } else {
02013                 req = DWC_ALLOC(sizeof(*req));
02014         }
02015 
02016         if (!req) {
02017                 return -DWC_E_NO_MEMORY;
02018         }
02019 
02020         /* Create the Isoc descs for this request which shall be the exact match
02021          * of the structure sent to us from the non-portable logic */
02022         res =
02023             dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
02024         if (res) {
02025                 DWC_WARN("Failed to init the Isoc descriptors");
02026                 DWC_FREE(req);
02027                 return res;
02028         }
02029 
02030         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02031 
02032         DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
02033         req->buf = buf;
02034         req->dma = dma_buf;
02035         req->length = buflen;
02036         req->sent_zlp = zero;
02037         req->priv = req_handle;
02038 
02039         //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02040         ep->dwc_ep.dma_addr = dma_buf;
02041         ep->dwc_ep.start_xfer_buff = buf;
02042         ep->dwc_ep.xfer_buff = buf;
02043         ep->dwc_ep.xfer_len = 0;
02044         ep->dwc_ep.xfer_count = 0;
02045         ep->dwc_ep.sent_zlp = 0;
02046         ep->dwc_ep.total_len = buflen;
02047 
02048         /* Add this request to the tail */
02049         DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
02050         ep->dwc_ep.xiso_queued_xfers++;
02051 
02052 //DWC_DEBUG("CP_0");
02053 //DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
02054 //prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
02055 //prn_ext_request(&req->ext_req);
02056 
02057         //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02058 
02059         /* If the req->status == ASAP  then check if there is any active transfer
02060          * for this endpoint. If no active transfers, then get the first entry
02061          * from the queue and start that transfer
02062          */
02063         if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
02064                 res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
02065                 if (res) {
02066                         DWC_WARN("Failed to start the next Isoc transfer");
02067                         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02068                         DWC_FREE(req);
02069                         return res;
02070                 }
02071         }
02072 
02073         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02074         return 0;
02075 }
02076 
02077 #endif
02078 /* END ifdef DWC_UTE_PER_IO ***************************************************/
02079 int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
02080                          uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
02081                          int zero, void *req_handle, int atomic_alloc)
02082 {
02083         dwc_irqflags_t flags;
02084         dwc_otg_pcd_request_t *req;
02085         dwc_otg_pcd_ep_t *ep;
02086         uint32_t max_transfer;
02087 
02088         ep = get_ep_from_handle(pcd, ep_handle);
02089         if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
02090                 DWC_WARN("bad ep\n");
02091                 return -DWC_E_INVALID;
02092         }
02093 
02094         if (atomic_alloc) {
02095                 req = DWC_ALLOC_ATOMIC(sizeof(*req));
02096         } else {
02097                 req = DWC_ALLOC(sizeof(*req));
02098         }
02099 
02100         if (!req) {
02101                 return -DWC_E_NO_MEMORY;
02102         }
02103         DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
02104         if (!GET_CORE_IF(pcd)->core_params->opt) {
02105                 if (ep->dwc_ep.num != 0) {
02106                         DWC_ERROR("queue req %p, len %d buf %p\n",
02107                                   req_handle, buflen, buf);
02108                 }
02109         }
02110 
02111         req->buf = buf;
02112         req->dma = dma_buf;
02113         req->length = buflen;
02114         req->sent_zlp = zero;
02115         req->priv = req_handle;
02116         req->dw_align_buf = NULL;
02117         if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
02118                         && !GET_CORE_IF(pcd)->dma_desc_enable)
02119                 req->dw_align_buf = DWC_DMA_ALLOC(buflen,
02120                                  &req->dw_align_buf_dma);
02121         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02122 
02123         /*
02124          * After adding request to the queue for IN ISOC wait for In Token Received
02125          * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token 
02126          * Received when EP is disabled interrupt to obtain starting microframe
02127          * (odd/even) start transfer
02128          */
02129         if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
02130         {
02131                 if (req != 0) {
02132                         depctl_data_t depctl = {.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl)};
02133                         ++pcd->request_pending;
02134 
02135                         DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
02136                         if (ep->dwc_ep.is_in)
02137                         {
02138                                 depctl.b.cnak = 1;
02139                                 DWC_WRITE_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl, depctl.d32);
02140                         }
02141                         
02142                         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02143                 }
02144                 return 0;
02145         }
02146 
02147         /*
02148          * For EP0 IN without premature status, zlp is required?
02149          */
02150         if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
02151                 DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
02152                 //_req->zero = 1;
02153         }
02154 
02155         /* Start the transfer */
02156         if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
02157                 /* EP0 Transfer? */
02158                 if (ep->dwc_ep.num == 0) {
02159                         switch (pcd->ep0state) {
02160                         case EP0_IN_DATA_PHASE:
02161                                 DWC_DEBUGPL(DBG_PCD,
02162                                             "%s ep0: EP0_IN_DATA_PHASE\n",
02163                                             __func__);
02164                                 break;
02165 
02166                         case EP0_OUT_DATA_PHASE:
02167                                 DWC_DEBUGPL(DBG_PCD,
02168                                             "%s ep0: EP0_OUT_DATA_PHASE\n",
02169                                             __func__);
02170                                 if (pcd->request_config) {
02171                                         /* Complete STATUS PHASE */
02172                                         ep->dwc_ep.is_in = 1;
02173                                         pcd->ep0state = EP0_IN_STATUS_PHASE;
02174                                 }
02175                                 break;
02176 
02177                         case EP0_IN_STATUS_PHASE:
02178                                 DWC_DEBUGPL(DBG_PCD,
02179                                             "%s ep0: EP0_IN_STATUS_PHASE\n",
02180                                             __func__);
02181                                 break;
02182 
02183                         default:
02184                                 DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
02185                                             pcd->ep0state);
02186                                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02187                                 return -DWC_E_SHUTDOWN;
02188                         }
02189 
02190                         ep->dwc_ep.dma_addr = dma_buf;
02191                         ep->dwc_ep.start_xfer_buff = buf;
02192                         ep->dwc_ep.xfer_buff = buf;
02193                         ep->dwc_ep.xfer_len = buflen;
02194                         ep->dwc_ep.xfer_count = 0;
02195                         ep->dwc_ep.sent_zlp = 0;
02196                         ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
02197 
02198                         if (zero) {
02199                                 if ((ep->dwc_ep.xfer_len %
02200                                      ep->dwc_ep.maxpacket == 0)
02201                                     && (ep->dwc_ep.xfer_len != 0)) {
02202                                         ep->dwc_ep.sent_zlp = 1;
02203                                 }
02204 
02205                         }
02206 
02207                         dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
02208                                                    &ep->dwc_ep);
02209                 }               // non-ep0 endpoints
02210                 else {
02211 #ifdef DWC_UTE_CFI
02212                         if (ep->dwc_ep.buff_mode != BM_STANDARD) {
02213                                 /* store the request length */
02214                                 ep->dwc_ep.cfi_req_len = buflen;
02215                                 pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
02216                                                                 ep, req);
02217                         } else {
02218 #endif
02219                                 max_transfer =
02220                                     GET_CORE_IF(ep->pcd)->
02221                                     core_params->max_transfer_size;
02222 
02223                                 /* Setup and start the Transfer */
02224                                 if (req->dw_align_buf){
02225                                         if (ep->dwc_ep.is_in)
02226                                                 dwc_memcpy(req->dw_align_buf, buf, buflen);
02227                                         ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
02228                                         ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
02229                                         ep->dwc_ep.xfer_buff = req->dw_align_buf;
02230                                 } else {
02231                                         ep->dwc_ep.dma_addr = dma_buf;
02232                                         ep->dwc_ep.start_xfer_buff = buf;
02233                                         ep->dwc_ep.xfer_buff = buf;     
02234                                 }
02235                                 ep->dwc_ep.xfer_len = 0;
02236                                 ep->dwc_ep.xfer_count = 0;
02237                                 ep->dwc_ep.sent_zlp = 0;
02238                                 ep->dwc_ep.total_len = buflen;
02239 
02240                                 ep->dwc_ep.maxxfer = max_transfer;
02241                                 if (GET_CORE_IF(pcd)->dma_desc_enable) {
02242                                         uint32_t out_max_xfer =
02243                                             DDMA_MAX_TRANSFER_SIZE -
02244                                             (DDMA_MAX_TRANSFER_SIZE % 4);
02245                                         if (ep->dwc_ep.is_in) {
02246                                                 if (ep->dwc_ep.maxxfer >
02247                                                     DDMA_MAX_TRANSFER_SIZE) {
02248                                                         ep->dwc_ep.maxxfer =
02249                                                             DDMA_MAX_TRANSFER_SIZE;
02250                                                 }
02251                                         } else {
02252                                                 if (ep->dwc_ep.maxxfer >
02253                                                     out_max_xfer) {
02254                                                         ep->dwc_ep.maxxfer =
02255                                                             out_max_xfer;
02256                                                 }
02257                                         }
02258                                 }
02259                                 if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
02260                                         ep->dwc_ep.maxxfer -=
02261                                             (ep->dwc_ep.maxxfer %
02262                                              ep->dwc_ep.maxpacket);
02263                                 }
02264 
02265                                 if (zero) {
02266                                         if ((ep->dwc_ep.total_len %
02267                                              ep->dwc_ep.maxpacket == 0)
02268                                             && (ep->dwc_ep.total_len != 0)) {
02269                                                 ep->dwc_ep.sent_zlp = 1;
02270                                         }
02271                                 }
02272 #ifdef DWC_UTE_CFI
02273                         }
02274 #endif
02275                         dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
02276                                                   &ep->dwc_ep);
02277                 }
02278         }
02279 
02280         if (req != 0) {
02281                 ++pcd->request_pending;
02282                 DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
02283                 if (ep->dwc_ep.is_in && ep->stopped
02284                     && !(GET_CORE_IF(pcd)->dma_enable)) {
02286                         diepmsk_data_t diepmsk = {.d32 = 0 };
02287                         diepmsk.b.intktxfemp = 1;
02288                         if (GET_CORE_IF(pcd)->multiproc_int_enable) {
02289                                 DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
02290                                                  dev_global_regs->
02291                                                  diepeachintmsk[ep->dwc_ep.num],
02292                                                  0, diepmsk.d32);
02293                         } else {
02294                                 DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
02295                                                  dev_global_regs->diepmsk, 0,
02296                                                  diepmsk.d32);
02297                         }
02298 
02299                 }
02300         }
02301         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02302 
02303         return 0;
02304 }
02305 
02306 int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
02307                            void *req_handle)
02308 {
02309         dwc_irqflags_t flags;
02310         dwc_otg_pcd_request_t *req;
02311         dwc_otg_pcd_ep_t *ep;
02312 
02313         ep = get_ep_from_handle(pcd, ep_handle);
02314         if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
02315                 DWC_WARN("bad argument\n");
02316                 return -DWC_E_INVALID;
02317         }
02318 
02319         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02320 
02321         /* make sure it's actually queued on this endpoint */
02322         DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
02323                 if (req->priv == (void *)req_handle) {
02324                         break;
02325                 }
02326         }
02327 
02328         if (req->priv != (void *)req_handle) {
02329                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02330                 return -DWC_E_INVALID;
02331         }
02332 
02333         if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
02334                 dwc_otg_request_done(ep, req, -DWC_E_RESTART);
02335         } else {
02336                 req = NULL;
02337         }
02338 
02339         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02340 
02341         return req ? 0 : -DWC_E_SHUTDOWN;
02342 
02343 }
02344 
02345 int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
02346 {
02347         dwc_otg_pcd_ep_t *ep;
02348         dwc_irqflags_t flags;
02349         int retval = 0;
02350 
02351         ep = get_ep_from_handle(pcd, ep_handle);
02352 
02353         if (!ep || (!ep->desc && ep != &pcd->ep0) ||
02354             (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
02355                 DWC_WARN("%s, bad ep\n", __func__);
02356                 return -DWC_E_INVALID;
02357         }
02358 
02359         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02360         if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
02361                 DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
02362                          ep->dwc_ep.is_in ? "IN" : "OUT");
02363                 retval = -DWC_E_AGAIN;
02364         } else if (value == 0) {
02365                 dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
02366         } else if (value == 1) {
02367                 if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
02368                         dtxfsts_data_t txstatus;
02369                         fifosize_data_t txfifosize;
02370 
02371                         txfifosize.d32 =
02372                             DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
02373                                            dtxfsiz[ep->dwc_ep.tx_fifo_num]);
02374                         txstatus.d32 =
02375                             DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
02376                                            in_ep_regs[ep->dwc_ep.num]->dtxfsts);
02377 
02378                         if (txstatus.b.txfspcavail < txfifosize.b.depth) {
02379                                 DWC_WARN("%s() Data In Tx Fifo\n", __func__);
02380                                 retval = -DWC_E_AGAIN;
02381                         } else {
02382                                 if (ep->dwc_ep.num == 0) {
02383                                         pcd->ep0state = EP0_STALL;
02384                                 }
02385 
02386                                 ep->stopped = 1;
02387                                 dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
02388                                                      &ep->dwc_ep);
02389                         }
02390                 } else {
02391                         if (ep->dwc_ep.num == 0) {
02392                                 pcd->ep0state = EP0_STALL;
02393                         }
02394 
02395                         ep->stopped = 1;
02396                         dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
02397                 }
02398         } else if (value == 2) {
02399                 ep->dwc_ep.stall_clear_flag = 0;
02400         } else if (value == 3) {
02401                 ep->dwc_ep.stall_clear_flag = 1;
02402         }
02403 
02404         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02405 
02406         return retval;
02407 }
02408 
02412 void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
02413 {
02414         dctl_data_t dctl = { 0 };
02415         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
02416         dsts_data_t dsts;
02417 
02418         dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
02419         if (!dsts.b.suspsts) {
02420                 DWC_WARN("Remote wakeup while is not in suspend state\n");
02421         }
02422         /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
02423         if (pcd->remote_wakeup_enable) {
02424                 if (set) {
02425 
02426                         if (core_if->adp_enable) {
02427                                 gpwrdn_data_t gpwrdn;
02428 
02429                                 dwc_otg_adp_probe_stop(core_if);
02430 
02431                                 /* Mask SRP detected interrupt from Power Down Logic */
02432                                 gpwrdn.d32 = 0;
02433                                 gpwrdn.b.srp_det_msk = 1;
02434                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
02435                                                  gpwrdn, gpwrdn.d32, 0);
02436 
02437                                 /* Disable Power Down Logic */
02438                                 gpwrdn.d32 = 0;
02439                                 gpwrdn.b.pmuactv = 1;
02440                                 DWC_MODIFY_REG32(&core_if->core_global_regs->
02441                                                  gpwrdn, gpwrdn.d32, 0);
02442 
02443                                 /*
02444                                  * Initialize the Core for Device mode.
02445                                  */
02446                                 core_if->op_state = B_PERIPHERAL;
02447                                 dwc_otg_core_init(core_if);
02448                                 dwc_otg_enable_global_interrupts(core_if);
02449                                 cil_pcd_start(core_if);
02450 
02451                                 dwc_otg_initiate_srp(core_if);
02452                         }
02453 
02454                         dctl.b.rmtwkupsig = 1;
02455                         DWC_MODIFY_REG32(&core_if->dev_if->
02456                                          dev_global_regs->dctl, 0, dctl.d32);
02457                         DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
02458 
02459                         dwc_mdelay(2);
02460                         DWC_MODIFY_REG32(&core_if->dev_if->
02461                                          dev_global_regs->dctl, dctl.d32, 0);
02462                         DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
02463                 }
02464         } else {
02465                 DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
02466         }
02467 }
02468 
02469 #ifdef CONFIG_USB_DWC_OTG_LPM
02470 
02473 void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
02474 {
02475         glpmcfg_data_t lpmcfg;
02476         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
02477 
02478         lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
02479 
02480         /* Check if we are in L1 state */
02481         if (!lpmcfg.b.prt_sleep_sts) {
02482                 DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
02483                 return;
02484         }
02485 
02486         /* Check if host allows remote wakeup */
02487         if (!lpmcfg.b.rem_wkup_en) {
02488                 DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
02489                 return;
02490         }
02491 
02492         /* Check if Resume OK */
02493         if (!lpmcfg.b.sleep_state_resumeok) {
02494                 DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
02495                 return;
02496         }
02497 
02498         lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
02499         lpmcfg.b.en_utmi_sleep = 0;
02500         lpmcfg.b.hird_thres &= (~(1 << 4));
02501         DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
02502 
02503         if (set) {
02504                 dctl_data_t dctl = {.d32 = 0 };
02505                 dctl.b.rmtwkupsig = 1;
02506                 /* Set RmtWkUpSig bit to start remote wakup signaling.
02507                  * Hardware will automatically clear this bit.
02508                  */
02509                 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
02510                                  0, dctl.d32);
02511                 DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
02512         }
02513 
02514 }
02515 #endif
02516 
02520 void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
02521 {
02522         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
02523         dwc_irqflags_t flags;
02524         if (dwc_otg_is_device_mode(core_if)) {
02525                 DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02526 #ifdef CONFIG_USB_DWC_OTG_LPM
02527                 if (core_if->lx_state == DWC_OTG_L1) {
02528                         dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
02529                 } else {
02530 #endif
02531                         dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
02532 #ifdef CONFIG_USB_DWC_OTG_LPM
02533                 }
02534 #endif
02535                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02536         }
02537         return;
02538 }
02539 
02540 void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
02541 {
02542         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
02543         dctl_data_t dctl = { 0 };
02544 
02545         if (dwc_otg_is_device_mode(core_if)) {
02546                 dctl.b.sftdiscon = 1;
02547                 DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
02548                 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
02549                 dwc_udelay(no_of_usecs);
02550                 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
02551                 
02552         } else{
02553                 DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
02554         }
02555         return;
02556 
02557 }
02558 
02559 int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
02560 {
02561         dsts_data_t dsts;
02562         gotgctl_data_t gotgctl;
02563 
02564         /*
02565          * This function starts the Protocol if no session is in progress. If
02566          * a session is already in progress, but the device is suspended,
02567          * remote wakeup signaling is started.
02568          */
02569 
02570         /* Check if valid session */
02571         gotgctl.d32 =
02572             DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
02573         if (gotgctl.b.bsesvld) {
02574                 /* Check if suspend state */
02575                 dsts.d32 =
02576                     DWC_READ_REG32(&
02577                                    (GET_CORE_IF(pcd)->dev_if->
02578                                     dev_global_regs->dsts));
02579                 if (dsts.b.suspsts) {
02580                         dwc_otg_pcd_remote_wakeup(pcd, 1);
02581                 }
02582         } else {
02583                 dwc_otg_pcd_initiate_srp(pcd);
02584         }
02585 
02586         return 0;
02587 
02588 }
02589 
02596 void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
02597 {
02598         dwc_irqflags_t flags;
02599         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
02600         dwc_otg_initiate_srp(GET_CORE_IF(pcd));
02601         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
02602 }
02603 
02604 int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
02605 {
02606         return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
02607 }
02608 
02609 int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
02610 {
02611         return GET_CORE_IF(pcd)->core_params->lpm_enable;
02612 }
02613 
02614 uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
02615 {
02616         return pcd->b_hnp_enable;
02617 }
02618 
02619 uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
02620 {
02621         return pcd->a_hnp_support;
02622 }
02623 
02624 uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
02625 {
02626         return pcd->a_alt_hnp_support;
02627 }
02628 
02629 int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
02630 {
02631         return pcd->remote_wakeup_enable;
02632 }
02633 
02634 #endif /* DWC_HOST_ONLY */

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