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: #79 $
00004  * $Date: 2009/04/10 $
00005  * $Change: 1230501 $
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 
00059 static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
00060 {
00061         int i;
00062         if (pcd->ep0.priv == handle) {
00063                 return &pcd->ep0;
00064         }
00065         for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
00066                 if (pcd->in_ep[i].priv == handle)
00067                         return &pcd->in_ep[i];
00068                 if (pcd->out_ep[i].priv == handle)
00069                         return &pcd->out_ep[i];
00070         }
00071 
00072         return NULL;
00073 }
00074 
00078 void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
00079                           int32_t status)
00080 {
00081         unsigned stopped = ep->stopped;
00082 
00083         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep);
00084         DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
00085 
00086         /* don't modify queue heads during completion callback */
00087         ep->stopped = 1;
00088         DWC_SPINUNLOCK(ep->pcd->lock);
00089         ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
00090                                 req->actual);
00091         DWC_SPINLOCK(ep->pcd->lock);
00092 
00093         if (ep->pcd->request_pending > 0) {
00094                 --ep->pcd->request_pending;
00095         }
00096 
00097         ep->stopped = stopped;
00098         dwc_free(req);
00099 }
00100 
00104 void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
00105 {
00106         dwc_otg_pcd_request_t *req;
00107 
00108         ep->stopped = 1;
00109 
00110         /* called with irqs blocked?? */
00111         while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
00112                 req = DWC_CIRCLEQ_FIRST(&ep->queue);
00113                 dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
00114         }
00115 }
00116 
00117 void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
00118                        const struct dwc_otg_pcd_function_ops *fops)
00119 {
00120         pcd->fops = fops;
00121 }
00122 
00129 static int32_t dwc_otg_pcd_start_cb(void *p)
00130 {
00131         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00132 
00133         /*
00134          * Initialized the Core for Device mode.
00135          */
00136         if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) {
00137                 dwc_otg_core_dev_init(GET_CORE_IF(pcd));
00138         }
00139         return 1;
00140 }
00141 
00143 #ifdef DWC_UTE_CFI
00144 uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
00145                               size_t buflen, int flags)
00146 {
00147         dwc_otg_pcd_ep_t *ep;
00148         ep = get_ep_from_handle(pcd, pep);
00149         return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
00150                                           flags);
00151 }
00152 #else
00153 uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
00154                               size_t buflen, int flags);
00155 #endif
00156 
00163 static int32_t dwc_otg_pcd_resume_cb(void *p)
00164 {
00165         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00166 
00167         if (pcd->fops->resume) {
00168                 pcd->fops->resume(pcd);
00169         }
00170 
00171         /* Stop the SRP timeout timer. */
00172         if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
00173             || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
00174                 if (GET_CORE_IF(pcd)->srp_timer_started) {
00175                         GET_CORE_IF(pcd)->srp_timer_started = 0;
00176                         DWC_TIMER_CANCEL(pcd->srp_timer);
00177                 }
00178         }
00179         return 1;
00180 }
00181 
00187 static int32_t dwc_otg_pcd_suspend_cb(void *p)
00188 {
00189         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00190 
00191         if (pcd->fops->suspend) {
00192                 pcd->fops->suspend(pcd);
00193         }
00194 
00195         return 1;
00196 }
00197 
00204 static int32_t dwc_otg_pcd_stop_cb(void *p)
00205 {
00206         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
00207         extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
00208 
00209         dwc_otg_pcd_stop(pcd);
00210         return 1;
00211 }
00212 
00216 static dwc_otg_cil_callbacks_t pcd_callbacks = {
00217         .start = dwc_otg_pcd_start_cb,
00218         .stop = dwc_otg_pcd_stop_cb,
00219         .suspend = dwc_otg_pcd_suspend_cb,
00220         .resume_wakeup = dwc_otg_pcd_resume_cb,
00221         .p = 0,                 /* Set at registration */
00222 };
00223 
00228 dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr,
00229                                                 uint32_t count)
00230 {
00231 
00232         return dwc_dma_alloc(count * sizeof(dwc_otg_dev_dma_desc_t), dma_desc_addr);
00233 }
00234 
00238 void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
00239                                 uint32_t dma_desc_addr, uint32_t count)
00240 {
00241         dwc_dma_free(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
00242                      dma_desc_addr);
00243 }
00244 
00245 #ifdef DWC_EN_ISOC
00246 
00254 void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
00255                                         dwc_ep_t * dwc_ep)
00256 {
00257 
00258         dsts_data_t dsts = {.d32 = 0 };
00259         depctl_data_t depctl = {.d32 = 0 };
00260         volatile uint32_t *addr;
00261         int i, j;
00262 
00263         if (dwc_ep->is_in)
00264                 dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
00265         else
00266                 dwc_ep->desc_cnt =
00267                     dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
00268                     dwc_ep->bInterval;
00269 
00271         dwc_ep->iso_desc_addr =
00272             dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
00273                                         dwc_ep->desc_cnt * 2);
00274         if (dwc_ep->desc_addr) {
00275                 DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
00276                 return;
00277         }
00278 
00279         dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
00280 
00282         if (dwc_ep->is_in == 0) {
00283                 dev_dma_desc_sts_t sts = {.d32 = 0 };
00284                 dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
00285                 dma_addr_t dma_ad;
00286                 uint32_t data_per_desc;
00287                 dwc_otg_dev_out_ep_regs_t *out_regs =
00288                     core_if->dev_if->out_ep_regs[dwc_ep->num];
00289                 int offset;
00290 
00291                 addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
00292                 dma_ad = (dma_addr_t) dwc_read_reg32(&(out_regs->doepdma));
00293 
00295                 dma_ad = dwc_ep->dma_addr0;
00296 
00297                 sts.b_iso_out.bs = BS_HOST_READY;
00298                 sts.b_iso_out.rxsts = 0;
00299                 sts.b_iso_out.l = 0;
00300                 sts.b_iso_out.sp = 0;
00301                 sts.b_iso_out.ioc = 0;
00302                 sts.b_iso_out.pid = 0;
00303                 sts.b_iso_out.framenum = 0;
00304 
00305                 offset = 0;
00306                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
00307                      i += dwc_ep->pkt_per_frm) {
00308 
00309                         for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
00310                                 data_per_desc =
00311                                     ((j + 1) * dwc_ep->maxpacket >
00312                                      dwc_ep->data_per_frame) ? dwc_ep->
00313                                     data_per_frame -
00314                                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00315 
00316                                 data_per_desc +=
00317                                     (data_per_desc % 4) ? (4 -
00318                                                            data_per_desc %
00319                                                            4) : 0;
00320                                 sts.b_iso_out.rxbytes = data_per_desc;
00321                                 dma_desc->buf = dma_ad;
00322                                 dma_desc->status.d32 = sts.d32;
00323 
00324                                 offset += data_per_desc;
00325                                 dma_desc++;
00326                                 dma_ad += data_per_desc;
00327                         }
00328                 }
00329 
00330                 for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
00331                         data_per_desc =
00332                             ((j + 1) * dwc_ep->maxpacket >
00333                              dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
00334                             j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00335                         data_per_desc +=
00336                             (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
00337                         sts.b_iso_out.rxbytes = data_per_desc;
00338                         dma_desc->buf = dma_ad;
00339                         dma_desc->status.d32 = sts.d32;
00340 
00341                         offset += data_per_desc;
00342                         dma_desc++;
00343                         dma_ad += data_per_desc;
00344                 }
00345 
00346                 sts.b_iso_out.ioc = 1;
00347                 data_per_desc =
00348                     ((j + 1) * dwc_ep->maxpacket >
00349                      dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
00350                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00351                 data_per_desc +=
00352                     (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
00353                 sts.b_iso_out.rxbytes = data_per_desc;
00354 
00355                 dma_desc->buf = dma_ad;
00356                 dma_desc->status.d32 = sts.d32;
00357                 dma_desc++;
00358 
00360                 sts.b_iso_out.ioc = 0;
00361                 dma_ad = dwc_ep->dma_addr1;
00362 
00363                 offset = 0;
00364                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
00365                      i += dwc_ep->pkt_per_frm) {
00366                         for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
00367                                 data_per_desc =
00368                                     ((j + 1) * dwc_ep->maxpacket >
00369                                      dwc_ep->data_per_frame) ? dwc_ep->
00370                                     data_per_frame -
00371                                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00372                                 data_per_desc +=
00373                                     (data_per_desc % 4) ? (4 -
00374                                                            data_per_desc %
00375                                                            4) : 0;
00376                                 sts.b_iso_out.rxbytes = data_per_desc;
00377                                 dma_desc->buf = dma_ad;
00378                                 dma_desc->status.d32 = sts.d32;
00379 
00380                                 offset += data_per_desc;
00381                                 dma_desc++;
00382                                 dma_ad += data_per_desc;
00383                         }
00384                 }
00385                 for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
00386                         data_per_desc =
00387                             ((j + 1) * dwc_ep->maxpacket >
00388                              dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
00389                             j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00390                         data_per_desc +=
00391                             (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
00392                         sts.b_iso_out.rxbytes = data_per_desc;
00393                         dma_desc->buf = dma_ad;
00394                         dma_desc->status.d32 = sts.d32;
00395 
00396                         offset += data_per_desc;
00397                         dma_desc++;
00398                         dma_ad += data_per_desc;
00399                 }
00400 
00401                 sts.b_iso_out.ioc = 1;
00402                 sts.b_iso_out.l = 1;
00403                 data_per_desc =
00404                     ((j + 1) * dwc_ep->maxpacket >
00405                      dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
00406                     j * dwc_ep->maxpacket : dwc_ep->maxpacket;
00407                 data_per_desc +=
00408                     (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
00409                 sts.b_iso_out.rxbytes = data_per_desc;
00410 
00411                 dma_desc->buf = dma_ad;
00412                 dma_desc->status.d32 = sts.d32;
00413 
00414                 dwc_ep->next_frame = 0;
00415 
00417                 dwc_write_reg32(&(out_regs->doepdma),
00418                                 (uint32_t) dwc_ep->iso_dma_desc_addr);
00419 
00420         }
00422         else {
00423                 dev_dma_desc_sts_t sts = {.d32 = 0 };
00424                 dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
00425                 dma_addr_t dma_ad;
00426                 dwc_otg_dev_in_ep_regs_t *in_regs =
00427                     core_if->dev_if->in_ep_regs[dwc_ep->num];
00428                 unsigned int frmnumber;
00429                 fifosize_data_t txfifosize, rxfifosize;
00430 
00431                 txfifosize.d32 =
00432                     dwc_read_reg32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
00433                                    dtxfsts);
00434                 rxfifosize.d32 =
00435                     dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
00436 
00437                 addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
00438 
00439                 dma_ad = dwc_ep->dma_addr0;
00440 
00441                 dsts.d32 =
00442                     dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
00443 
00444                 sts.b_iso_in.bs = BS_HOST_READY;
00445                 sts.b_iso_in.txsts = 0;
00446                 sts.b_iso_in.sp =
00447                     (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
00448                 sts.b_iso_in.ioc = 0;
00449                 sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
00450 
00451                 frmnumber = dwc_ep->next_frame;
00452 
00453                 sts.b_iso_in.framenum = frmnumber;
00454                 sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
00455                 sts.b_iso_in.l = 0;
00456 
00458                 for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
00459                         dma_desc->buf = dma_ad;
00460                         dma_desc->status.d32 = sts.d32;
00461                         dma_desc++;
00462 
00463                         dma_ad += dwc_ep->data_per_frame;
00464                         sts.b_iso_in.framenum += dwc_ep->bInterval;
00465                 }
00466 
00467                 sts.b_iso_in.ioc = 1;
00468                 dma_desc->buf = dma_ad;
00469                 dma_desc->status.d32 = sts.d32;
00470                 ++dma_desc;
00471 
00473                 sts.b_iso_in.ioc = 0;
00474                 dma_ad = dwc_ep->dma_addr1;
00475 
00476                 for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
00477                      i += dwc_ep->pkt_per_frm) {
00478                         dma_desc->buf = dma_ad;
00479                         dma_desc->status.d32 = sts.d32;
00480                         dma_desc++;
00481 
00482                         dma_ad += dwc_ep->data_per_frame;
00483                         sts.b_iso_in.framenum += dwc_ep->bInterval;
00484 
00485                         sts.b_iso_in.ioc = 0;
00486                 }
00487                 sts.b_iso_in.ioc = 1;
00488                 sts.b_iso_in.l = 1;
00489 
00490                 dma_desc->buf = dma_ad;
00491                 dma_desc->status.d32 = sts.d32;
00492 
00493                 dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
00494 
00496                 dwc_write_reg32(&(in_regs->diepdma),
00497                                 (uint32_t) dwc_ep->iso_dma_desc_addr);
00498         }
00500         depctl.d32 = 0;
00501         depctl.b.epena = 1;
00502         depctl.b.usbactep = 1;
00503         depctl.b.cnak = 1;
00504 
00505         dwc_modify_reg32(addr, depctl.d32, depctl.d32);
00506         depctl.d32 = dwc_read_reg32(addr);
00507 }
00508 
00517 void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
00518                                        dwc_ep_t * ep)
00519 {
00520         depctl_data_t depctl = {.d32 = 0 };
00521         volatile uint32_t *addr;
00522 
00523         if (ep->is_in) {
00524                 addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
00525         } else {
00526                 addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
00527         }
00528 
00529         if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
00530                 return;
00531         } else {
00532                 deptsiz_data_t deptsiz = {.d32 = 0 };
00533 
00534                 ep->xfer_len =
00535                     ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
00536                 ep->pkt_cnt =
00537                     (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
00538                 ep->xfer_count = 0;
00539                 ep->xfer_buff =
00540                     (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
00541                 ep->dma_addr =
00542                     (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
00543 
00544                 if (ep->is_in) {
00545                         /* Program the transfer size and packet count
00546                          *      as follows: xfersize = N * maxpacket +
00547                          *      short_packet pktcnt = N + (short_packet
00548                          *      exist ? 1 : 0)  
00549                          */
00550                         deptsiz.b.mc = ep->pkt_per_frm;
00551                         deptsiz.b.xfersize = ep->xfer_len;
00552                         deptsiz.b.pktcnt =
00553                             (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
00554                         dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
00555                                         dieptsiz, deptsiz.d32);
00556 
00557                         /* Write the DMA register */
00558                         dwc_write_reg32(&
00559                                         (core_if->dev_if->in_ep_regs[ep->num]->
00560                                          diepdma), (uint32_t) ep->dma_addr);
00561 
00562                 } else {
00563                         deptsiz.b.pktcnt =
00564                             (ep->xfer_len + (ep->maxpacket - 1)) /
00565                             ep->maxpacket;
00566                         deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
00567 
00568                         dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
00569                                         doeptsiz, deptsiz.d32);
00570 
00571                         /* Write the DMA register */
00572                         dwc_write_reg32(&
00573                                         (core_if->dev_if->out_ep_regs[ep->num]->
00574                                          doepdma), (uint32_t) ep->dma_addr);
00575 
00576                 }
00578                 depctl.d32 = 0;
00579                 dwc_modify_reg32(addr, depctl.d32, depctl.d32);
00580 
00581                 depctl.b.epena = 1;
00582                 depctl.b.cnak = 1;
00583 
00584                 dwc_modify_reg32(addr, depctl.d32, depctl.d32);
00585         }
00586 }
00587 
00598 static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
00599                                           dwc_ep_t * ep)
00600 {
00601         if (core_if->dma_enable) {
00602                 if (core_if->dma_desc_enable) {
00603                         if (ep->is_in) {
00604                                 ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
00605                         } else {
00606                                 ep->desc_cnt = ep->pkt_cnt;
00607                         }
00608                         dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
00609                 } else {
00610                         if (core_if->pti_enh_enable) {
00611                                 dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
00612                         } else {
00613                                 ep->cur_pkt_addr =
00614                                     (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
00615                                     xfer_buff0;
00616                                 ep->cur_pkt_dma_addr =
00617                                     (ep->proc_buf_num) ? ep->dma_addr1 : ep->
00618                                     dma_addr0;
00619                                 dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
00620                         }
00621                 }
00622         } else {
00623                 ep->cur_pkt_addr =
00624                     (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
00625                 ep->cur_pkt_dma_addr =
00626                     (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
00627                 dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
00628         }
00629 }
00630 
00641 void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
00642 {
00643         depctl_data_t depctl = {.d32 = 0 };
00644         volatile uint32_t *addr;
00645 
00646         if (ep->is_in == 1) {
00647                 addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
00648         } else {
00649                 addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
00650         }
00651 
00652         /* disable the ep */
00653         depctl.d32 = dwc_read_reg32(addr);
00654 
00655         depctl.b.epdis = 1;
00656         depctl.b.snak = 1;
00657 
00658         dwc_write_reg32(addr, depctl.d32);
00659 
00660         if (core_if->dma_desc_enable &&
00661             ep->iso_desc_addr && ep->iso_dma_desc_addr) {
00662                 dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
00663                                            ep->iso_dma_desc_addr,
00664                                            ep->desc_cnt * 2);
00665         }
00666 
00667         /* reset varibales */
00668         ep->dma_addr0 = 0;
00669         ep->dma_addr1 = 0;
00670         ep->xfer_buff0 = 0;
00671         ep->xfer_buff1 = 0;
00672         ep->data_per_frame = 0;
00673         ep->data_pattern_frame = 0;
00674         ep->sync_frame = 0;
00675         ep->buf_proc_intrvl = 0;
00676         ep->bInterval = 0;
00677         ep->proc_buf_num = 0;
00678         ep->pkt_per_frm = 0;
00679         ep->pkt_per_frm = 0;
00680         ep->desc_cnt = 0;
00681         ep->iso_desc_addr = 0;
00682         ep->iso_dma_desc_addr = 0;
00683 }
00684 
00685 int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
00686                              uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
00687                              dwc_dma_t dma1, int sync_frame, int dp_frame,
00688                              int data_per_frame, int start_frame,
00689                              int buf_proc_intrvl, void *req_handle,
00690                              int atomic_alloc)
00691 {
00692         dwc_otg_pcd_ep_t *ep;
00693         uint64_t flags = 0;
00694         dwc_ep_t *dwc_ep;
00695         int32_t frm_data;
00696         dsts_data_t dsts;
00697         dwc_otg_core_if_t *core_if;
00698 
00699         ep = get_ep_from_handle(pcd, ep_handle);
00700 
00701         if (!ep->desc || ep->dwc_ep.num == 0) {
00702                 DWC_WARN("bad ep\n");
00703                 return -DWC_E_INVALID;
00704         }
00705 
00706         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
00707         core_if = GET_CORE_IF(pcd);
00708         dwc_ep = &ep->dwc_ep;
00709 
00710         if (ep->iso_req_handle) {
00711                 DWC_WARN("ISO request in progress\n");
00712         }
00713 
00714         dwc_ep->dma_addr0 = dma0;
00715         dwc_ep->dma_addr1 = dma1;
00716 
00717         dwc_ep->xfer_buff0 = buf0;
00718         dwc_ep->xfer_buff1 = buf1;
00719 
00720         dwc_ep->data_per_frame = data_per_frame;
00721 
00723         dwc_ep->data_pattern_frame = dp_frame;
00724         dwc_ep->sync_frame = sync_frame;
00725 
00726         dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
00727 
00728         dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
00729 
00730         dwc_ep->proc_buf_num = 0;
00731 
00732         dwc_ep->pkt_per_frm = 0;
00733         frm_data = ep->dwc_ep.data_per_frame;
00734         while (frm_data > 0) {
00735                 dwc_ep->pkt_per_frm++;
00736                 frm_data -= ep->dwc_ep.maxpacket;
00737         }
00738 
00739         dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
00740 
00741         if (start_frame == -1) {
00742                 dwc_ep->next_frame = dsts.b.soffn + 1;
00743                 if (dwc_ep->bInterval != 1) {
00744                         dwc_ep->next_frame =
00745                             dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
00746                                                   dwc_ep->next_frame %
00747                                                   dwc_ep->bInterval);
00748                 }
00749         } else {
00750                 dwc_ep->next_frame = start_frame;
00751         }
00752 
00753         if (!core_if->pti_enh_enable) {
00754                 dwc_ep->pkt_cnt =
00755                     dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
00756                     dwc_ep->bInterval;
00757         } else {
00758                 dwc_ep->pkt_cnt =
00759                     (dwc_ep->data_per_frame *
00760                      (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
00761                      - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
00762         }
00763 
00764         if (core_if->dma_desc_enable) {
00765                 dwc_ep->desc_cnt =
00766                     dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
00767                     dwc_ep->bInterval;
00768         }
00769 
00770         if (atomic_alloc) {
00771                 dwc_ep->pkt_info =
00772                     dwc_alloc_atomic(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
00773         } else {
00774                 dwc_ep->pkt_info =
00775                     dwc_alloc(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
00776         }
00777         if (!dwc_ep->pkt_info) {
00778                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00779                 return -DWC_E_NO_MEMORY;
00780         }
00781         if (core_if->pti_enh_enable) {
00782                 dwc_memset(dwc_ep->pkt_info, 0,
00783                            sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
00784         }
00785 
00786         dwc_ep->cur_pkt = 0;
00787         ep->iso_req_handle = req_handle;
00788 
00789         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00790         dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
00791         return 0;
00792 }
00793 
00794 int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
00795                             void *req_handle)
00796 {
00797         uint64_t flags = 0;
00798         dwc_otg_pcd_ep_t *ep;
00799         dwc_ep_t *dwc_ep;
00800 
00801         ep = get_ep_from_handle(pcd, ep_handle);
00802         if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
00803                 DWC_WARN("bad ep\n");
00804                 return -DWC_E_INVALID;
00805         }
00806         dwc_ep = &ep->dwc_ep;
00807 
00808         dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
00809 
00810         dwc_free(dwc_ep->pkt_info);
00811         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
00812         if (ep->iso_req_handle != req_handle) {
00813                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00814                 return -DWC_E_INVALID;
00815         }
00816 
00817         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
00818 
00819         ep->iso_req_handle = 0;
00820         return 0;
00821 }
00822 
00830 void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
00831                              void *req_handle)
00832 {
00833         int i;
00834         dwc_ep_t *dwc_ep;
00835 
00836         dwc_ep = &ep->dwc_ep;
00837 
00838         DWC_SPINUNLOCK(ep->pcd->lock);
00839         pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
00840                                  dwc_ep->proc_buf_num ^ 0x1);
00841         DWC_SPINLOCK(ep->pcd->lock);
00842 
00843         for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
00844                 dwc_ep->pkt_info[i].status = 0;
00845                 dwc_ep->pkt_info[i].offset = 0;
00846                 dwc_ep->pkt_info[i].length = 0;
00847         }
00848 }
00849 
00850 int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
00851                                      void *iso_req_handle)
00852 {
00853         dwc_otg_pcd_ep_t *ep;
00854         dwc_ep_t *dwc_ep;
00855 
00856         ep = get_ep_from_handle(pcd, ep_handle);
00857         dwc_ep = &ep->dwc_ep;
00858 
00859         return dwc_ep->pkt_cnt;
00860 }
00861 
00862 void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
00863                                        void *iso_req_handle, int packet,
00864                                        int *status, int *actual, int *offset)
00865 {
00866         dwc_otg_pcd_ep_t *ep;
00867         dwc_ep_t *dwc_ep;
00868 
00869         ep = get_ep_from_handle(pcd, ep_handle);
00870         dwc_ep = &ep->dwc_ep;
00871 
00872         *status = dwc_ep->pkt_info[packet].status;
00873         *actual = dwc_ep->pkt_info[packet].length;
00874         *offset = dwc_ep->pkt_info[packet].offset;
00875 }
00876 
00877 #endif                          /* DWC_EN_ISOC */
00878 
00879 static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
00880                                 uint32_t is_in, uint32_t ep_num)
00881 {
00882         /* Init EP structure */
00883         pcd_ep->desc = 0;
00884         pcd_ep->pcd = pcd;
00885         pcd_ep->stopped = 1;
00886         pcd_ep->queue_sof = 0;
00887 
00888         /* Init DWC ep structure */
00889         pcd_ep->dwc_ep.is_in = is_in;
00890         pcd_ep->dwc_ep.num = ep_num;
00891         pcd_ep->dwc_ep.active = 0;
00892         pcd_ep->dwc_ep.tx_fifo_num = 0;
00893         /* Control until ep is actvated */
00894         pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
00895         pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
00896         pcd_ep->dwc_ep.dma_addr = 0;
00897         pcd_ep->dwc_ep.start_xfer_buff = 0;
00898         pcd_ep->dwc_ep.xfer_buff = 0;
00899         pcd_ep->dwc_ep.xfer_len = 0;
00900         pcd_ep->dwc_ep.xfer_count = 0;
00901         pcd_ep->dwc_ep.sent_zlp = 0;
00902         pcd_ep->dwc_ep.total_len = 0;
00903         pcd_ep->dwc_ep.desc_addr = 0;
00904         pcd_ep->dwc_ep.dma_desc_addr = 0;
00905         DWC_CIRCLEQ_INIT(&pcd_ep->queue);
00906 }
00907 
00911 static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
00912 {
00913         int i;
00914         uint32_t hwcfg1;
00915         dwc_otg_pcd_ep_t *ep;
00916         int in_ep_cntr, out_ep_cntr;
00917         uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
00918         uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
00919 
00923         ep = &pcd->ep0;
00924         dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
00925 
00926         in_ep_cntr = 0;
00927         hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
00928         for (i = 1; in_ep_cntr < num_in_eps; i++) {
00929                 if ((hwcfg1 & 0x1) == 0) {
00930                         dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
00931                         in_ep_cntr++;
00937                         dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
00938 
00939                         DWC_CIRCLEQ_INIT(&ep->queue);
00940                 }
00941                 hwcfg1 >>= 2;
00942         }
00943 
00944         out_ep_cntr = 0;
00945         hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
00946         for (i = 1; out_ep_cntr < num_out_eps; i++) {
00947                 if ((hwcfg1 & 0x1) == 0) {
00948                         dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
00949                         out_ep_cntr++;
00955                         dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
00956                         DWC_CIRCLEQ_INIT(&ep->queue);
00957                 }
00958                 hwcfg1 >>= 2;
00959         }
00960 
00961         pcd->ep0state = EP0_DISCONNECT;
00962         pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
00963         pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
00964 }
00965 
00970 static void srp_timeout(void *ptr)
00971 {
00972         gotgctl_data_t gotgctl;
00973         dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
00974         volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
00975 
00976         gotgctl.d32 = dwc_read_reg32(addr);
00977 
00978         core_if->srp_timer_started = 0;
00979 
00980         if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
00981             (core_if->core_params->i2c_enable)) {
00982                 DWC_PRINTF("SRP Timeout\n");
00983 
00984                 if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
00985                         if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
00986                                 core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->
00987                                                                p);
00988                         }
00989 
00990                         /* Clear Session Request */
00991                         gotgctl.d32 = 0;
00992                         gotgctl.b.sesreq = 1;
00993                         dwc_modify_reg32(&core_if->core_global_regs->gotgctl,
00994                                          gotgctl.d32, 0);
00995 
00996                         core_if->srp_success = 0;
00997                 } else {
00998                         __DWC_ERROR("Device not connected/responding\n");
00999                         gotgctl.b.sesreq = 0;
01000                         dwc_write_reg32(addr, gotgctl.d32);
01001                 }
01002         } else if (gotgctl.b.sesreq) {
01003                 DWC_PRINTF("SRP Timeout\n");
01004 
01005                 __DWC_ERROR("Device not connected/responding\n");
01006                 gotgctl.b.sesreq = 0;
01007                 dwc_write_reg32(addr, gotgctl.d32);
01008         } else {
01009                 DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
01010         }
01011 }
01012 
01017 extern void start_next_request(dwc_otg_pcd_ep_t * ep);
01018 
01019 static void start_xfer_tasklet_func(void *data)
01020 {
01021         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
01022         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01023 
01024         int i;
01025         depctl_data_t diepctl;
01026 
01027         DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
01028 
01029         diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl);
01030 
01031         if (pcd->ep0.queue_sof) {
01032                 pcd->ep0.queue_sof = 0;
01033                 start_next_request(&pcd->ep0);
01034                 // break;
01035         }
01036 
01037         for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
01038                 depctl_data_t diepctl;
01039                 diepctl.d32 =
01040                     dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl);
01041 
01042                 if (pcd->in_ep[i].queue_sof) {
01043                         pcd->in_ep[i].queue_sof = 0;
01044                         start_next_request(&pcd->in_ep[i]);
01045                         // break;
01046                 }
01047         }
01048 
01049         return;
01050 }
01051 
01056 dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
01057 {
01058         dwc_otg_pcd_t *pcd = 0;
01059         dwc_otg_dev_if_t *dev_if;
01060 
01061         /*
01062          * Allocate PCD structure
01063          */
01064         pcd = dwc_alloc(sizeof(dwc_otg_pcd_t));
01065 
01066         if (pcd == 0) {
01067                 return NULL;
01068         }
01069 
01070         pcd->lock = DWC_SPINLOCK_ALLOC();
01071         pcd->core_if = core_if;
01072         if (!pcd->lock) {
01073                 DWC_ERROR("Could not allocate lock for pcd");
01074                 dwc_free(pcd);
01075                 return NULL;
01076         }
01077         dev_if = core_if->dev_if;
01078 
01079         if (core_if->hwcfg4.b.ded_fifo_en) {
01080                 DWC_PRINTF("Dedicated Tx FIFOs mode\n");
01081         } else {
01082                 DWC_PRINTF("Shared Tx FIFO mode\n");
01083         }
01084 
01085         /*
01086          * Initialized the Core for Device mode.
01087          */
01088         if (dwc_otg_is_device_mode(core_if)) {
01089                 dwc_otg_core_dev_init(core_if);
01090         }
01091 
01092         /*
01093          * Register the PCD Callbacks.
01094          */
01095         dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
01096 
01097         /*
01098          * Initialize the DMA buffer for SETUP packets
01099          */
01100         if (GET_CORE_IF(pcd)->dma_enable) {
01101                 pcd->setup_pkt =
01102                     dwc_dma_alloc(sizeof(*pcd->setup_pkt) * 5,
01103                                   &pcd->setup_pkt_dma_handle);
01104                 if (pcd->setup_pkt == 0) {
01105                         dwc_free(pcd);
01106                         return NULL;
01107                 }
01108 
01109                 pcd->status_buf =
01110                     dwc_dma_alloc(sizeof(uint16_t),
01111                                   &pcd->status_buf_dma_handle);
01112                 if (pcd->status_buf == 0) {
01113                         dwc_dma_free(sizeof(*pcd->setup_pkt) * 5,
01114                                      pcd->setup_pkt, pcd->setup_pkt_dma_handle);
01115                         dwc_free(pcd);
01116                         return NULL;
01117                 }
01118 
01119                 if (GET_CORE_IF(pcd)->dma_desc_enable) {
01120                         dev_if->setup_desc_addr[0] =
01121                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01122                                                         dma_setup_desc_addr[0],
01123                                                         1);
01124                         dev_if->setup_desc_addr[1] =
01125                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01126                                                         dma_setup_desc_addr[1],
01127                                                         1);
01128                         dev_if->in_desc_addr =
01129                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01130                                                         dma_in_desc_addr, 1);
01131                         dev_if->out_desc_addr =
01132                             dwc_otg_ep_alloc_desc_chain(&dev_if->
01133                                                         dma_out_desc_addr, 1);
01134 
01135                         if (dev_if->setup_desc_addr[0] == 0
01136                             || dev_if->setup_desc_addr[1] == 0
01137                             || dev_if->in_desc_addr == 0
01138                             || dev_if->out_desc_addr == 0) {
01139 
01140                                 if (dev_if->out_desc_addr)
01141                                         dwc_otg_ep_free_desc_chain(dev_if->
01142                                                                    out_desc_addr,
01143                                                                    dev_if->
01144                                                                    dma_out_desc_addr,
01145                                                                    1);
01146                                 if (dev_if->in_desc_addr)
01147                                         dwc_otg_ep_free_desc_chain(dev_if->
01148                                                                    in_desc_addr,
01149                                                                    dev_if->
01150                                                                    dma_in_desc_addr,
01151                                                                    1);
01152                                 if (dev_if->setup_desc_addr[1])
01153                                         dwc_otg_ep_free_desc_chain(dev_if->
01154                                                                    setup_desc_addr
01155                                                                    [1],
01156                                                                    dev_if->
01157                                                                    dma_setup_desc_addr
01158                                                                    [1], 1);
01159                                 if (dev_if->setup_desc_addr[0])
01160                                         dwc_otg_ep_free_desc_chain(dev_if->
01161                                                                    setup_desc_addr
01162                                                                    [0],
01163                                                                    dev_if->
01164                                                                    dma_setup_desc_addr
01165                                                                    [0], 1);
01166 
01167                                 dwc_dma_free(sizeof(*pcd->setup_pkt) * 5,
01168                                              pcd->setup_pkt,
01169                                              pcd->setup_pkt_dma_handle);
01170                                 dwc_dma_free(sizeof(*pcd->status_buf),
01171                                              pcd->status_buf,
01172                                              pcd->status_buf_dma_handle);
01173 
01174                                 dwc_free(pcd);
01175 
01176                                 return NULL;
01177                         }
01178                 }
01179         } else {
01180                 pcd->setup_pkt = dwc_alloc(sizeof(*pcd->setup_pkt) * 5);
01181                 if (pcd->setup_pkt == 0) {
01182                         dwc_free(pcd);
01183                         return NULL;
01184                 }
01185 
01186                 pcd->status_buf = dwc_alloc(sizeof(uint16_t));
01187                 if (pcd->status_buf == 0) {
01188                         dwc_free(pcd->setup_pkt);
01189                         dwc_free(pcd);
01190                         return NULL;
01191                 }
01192         }
01193 
01194         dwc_otg_pcd_reinit(pcd);
01195 
01196         /* Allocate the cfi object for the PCD */
01197 #ifdef DWC_UTE_CFI
01198         pcd->cfi = dwc_alloc(sizeof(cfiobject_t));
01199         if (NULL == pcd->cfi)
01200                 return NULL;
01201         if (init_cfi(pcd->cfi)) {
01202                 CFI_INFO("%s: Failed to init the CFI object\n", __func__);
01203                 return NULL;
01204         }
01205 #endif
01206 
01207         /* Initialize tasklets */
01208         pcd->start_xfer_tasklet = DWC_TASK_ALLOC(start_xfer_tasklet_func, pcd);
01209         pcd->test_mode_tasklet = DWC_TASK_ALLOC(do_test_mode, pcd);
01210         /* Initialize timer */
01211         pcd->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
01212         return pcd;
01213 }
01214 
01215 void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
01216 {
01217         dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
01218 
01219         if (GET_CORE_IF(pcd)->dma_enable) {
01220                 dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
01221                              pcd->setup_pkt_dma_handle);
01222                 dwc_dma_free(sizeof(uint16_t), pcd->status_buf,
01223                              pcd->status_buf_dma_handle);
01224                 if (GET_CORE_IF(pcd)->dma_desc_enable) {
01225                         dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
01226                                                    dev_if->
01227                                                    dma_setup_desc_addr[0], 1);
01228                         dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
01229                                                    dev_if->
01230                                                    dma_setup_desc_addr[1], 1);
01231                         dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
01232                                                    dev_if->dma_in_desc_addr, 1);
01233                         dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
01234                                                    dev_if->dma_out_desc_addr,
01235                                                    1);
01236                 }
01237         } else {
01238                 dwc_free(pcd->setup_pkt);
01239                 dwc_free(pcd->status_buf);
01240         }
01241         DWC_SPINLOCK_FREE(pcd->lock);
01242         DWC_TASK_FREE(pcd->start_xfer_tasklet);
01243         DWC_TASK_FREE(pcd->test_mode_tasklet);
01244         DWC_TIMER_FREE(pcd->srp_timer);
01245 
01246 /* Release the CFI object's dynamic memory */
01247 #ifdef DWC_UTE_CFI
01248         if (pcd->cfi->ops.release) {
01249                 pcd->cfi->ops.release(pcd->cfi);
01250         }
01251 #endif
01252 
01253         dwc_free(pcd);
01254 }
01255 
01256 uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
01257 {
01258         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01259 
01260         if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
01261             ((core_if->hwcfg2.b.hs_phy_type == 2) &&
01262              (core_if->hwcfg2.b.fs_phy_type == 1) &&
01263              (core_if->core_params->ulpi_fs_ls))) {
01264                 return 0;
01265         }
01266 
01267         return 1;
01268 }
01269 
01270 uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
01271 {
01272         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01273         gusbcfg_data_t usbcfg = {.d32 = 0 };
01274 
01275         usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
01276         if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
01277                 return 0;
01278         }
01279 
01280         return 1;
01281 }
01282 
01287 static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
01288 {
01289         uint32_t TxMsk = 1;
01290         int i;
01291 
01292         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
01293                 if ((TxMsk & core_if->tx_msk) == 0) {
01294                         core_if->tx_msk |= TxMsk;
01295                         return i + 1;
01296                 }
01297                 TxMsk <<= 1;
01298         }
01299         return 0;
01300 }
01301 
01306 static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
01307 {
01308         uint32_t PerTxMsk = 1;
01309         int i;
01310         for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
01311                 if ((PerTxMsk & core_if->p_tx_msk) == 0) {
01312                         core_if->p_tx_msk |= PerTxMsk;
01313                         return i + 1;
01314                 }
01315                 PerTxMsk <<= 1;
01316         }
01317         return 0;
01318 }
01319 
01324 static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
01325                                   uint32_t fifo_num)
01326 {
01327         core_if->p_tx_msk =
01328             (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
01329 }
01330 
01335 static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
01336 {
01337         core_if->tx_msk =
01338             (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
01339 }
01340 
01341 int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
01342                           const uint8_t * ep_desc, void *usb_ep)
01343 {
01344         int num, dir;
01345         dwc_otg_pcd_ep_t *ep = 0;
01346         const usb_endpoint_descriptor_t *desc;
01347         uint64_t flags;
01348         int retval = 0;
01349 
01350         desc = (const usb_endpoint_descriptor_t *)ep_desc;
01351 
01352         if (!desc) {
01353                 pcd->ep0.priv = usb_ep;
01354                 ep = &pcd->ep0;
01355                 retval = -DWC_E_INVALID;
01356                 goto out;
01357         }
01358 
01359         num = UE_GET_ADDR(desc->bEndpointAddress);
01360         dir = UE_GET_DIR(desc->bEndpointAddress);
01361 
01362         if (!desc->wMaxPacketSize) {
01363                 DWC_WARN("bad maxpacketsize\n");
01364                 retval = -DWC_E_INVALID;
01365                 goto out;
01366         }
01367 
01368         if (dir == UE_DIR_IN) {
01369                 ep = &pcd->in_ep[num - 1];
01370         } else {
01371                 ep = &pcd->out_ep[num - 1];
01372         }
01373 
01374         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01375 
01376         ep->desc = desc;
01377         ep->priv = usb_ep;
01378 
01379         /*
01380          * Activate the EP
01381          */
01382         ep->stopped = 0;
01383 
01384         ep->dwc_ep.is_in = (dir == UE_DIR_IN);
01385         ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
01386 
01387         ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
01388 
01389         if (ep->dwc_ep.is_in) {
01390                 if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
01391                         ep->dwc_ep.tx_fifo_num = 0;
01392 
01393                         if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
01394                                 /*
01395                                  * if ISOC EP then assign a Periodic Tx FIFO.
01396                                  */
01397                                 ep->dwc_ep.tx_fifo_num =
01398                                     assign_perio_tx_fifo(GET_CORE_IF(pcd));
01399                         }
01400                 } else {
01401                         /*
01402                          * if Dedicated FIFOs mode is on then assign a Tx FIFO.
01403                          */
01404                         ep->dwc_ep.tx_fifo_num =
01405                             assign_tx_fifo(GET_CORE_IF(pcd));
01406 
01407                 }
01408         }
01409         /* Set initial data PID. */
01410         if (ep->dwc_ep.type == UE_BULK) {
01411                 ep->dwc_ep.data_pid_start = 0;
01412         }
01413 
01414         /* Alloc DMA Descriptors */
01415         if (GET_CORE_IF(pcd)->dma_desc_enable) {
01416                 if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
01417                         ep->dwc_ep.desc_addr =
01418                             dwc_otg_ep_alloc_desc_chain(&ep->dwc_ep.
01419                                                         dma_desc_addr,
01420                                                         MAX_DMA_DESC_CNT);
01421                         if (!ep->dwc_ep.desc_addr) {
01422                                 DWC_WARN("%s, can't allocate DMA descriptor\n",
01423                                          __func__);
01424                                 retval = -DWC_E_SHUTDOWN;
01425                                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01426                                 goto out;
01427                         }
01428                 }
01429         }
01430 
01431         DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
01432                     (ep->dwc_ep.is_in ? "IN" : "OUT"),
01433                     ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
01434 
01435         dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
01436 
01437 #ifdef DWC_UTE_CFI
01438         if (pcd->cfi->ops.ep_enable) {
01439                 pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
01440         }
01441 #endif
01442 
01443         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01444 
01445       out:
01446         return retval;
01447 }
01448 
01449 int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
01450 {
01451         dwc_otg_pcd_ep_t *ep;
01452         uint64_t flags;
01453         dwc_otg_dev_dma_desc_t *desc_addr;
01454         dwc_dma_t dma_desc_addr;
01455 
01456         ep = get_ep_from_handle(pcd, ep_handle);
01457 
01458         if (!ep || !ep->desc) {
01459                 DWC_DEBUGPL(DBG_PCD, "%s, %d %s not enabled\n", __func__,
01460                             ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT");
01461                 return -DWC_E_INVALID;
01462         }
01463 
01464         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01465 
01466         dwc_otg_request_nuke(ep);
01467 
01468         dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
01469         ep->desc = 0;
01470         ep->stopped = 1;
01471 
01472         if (ep->dwc_ep.is_in) {
01473                 dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
01474                 release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
01475                 release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
01476         }
01477 
01478         /* Free DMA Descriptors */
01479         if (GET_CORE_IF(pcd)->dma_desc_enable) {
01480                 if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
01481                         desc_addr = ep->dwc_ep.desc_addr;
01482                         dma_desc_addr = ep->dwc_ep.dma_desc_addr;
01483 
01484                         /* Cannot call dma_free_coherent() with IRQs disabled */
01485                         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01486                         dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
01487                                                    MAX_DMA_DESC_CNT);
01488 
01489                         goto out_unlocked;
01490                 }
01491         }
01492 
01493         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01494 
01495       out_unlocked:
01496         DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
01497                     ep->dwc_ep.is_in ? "IN" : "OUT");
01498         return 0;
01499 
01500 }
01501 
01502 int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
01503                          uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
01504                          int zero, void *req_handle, int atomic_alloc)
01505 {
01506         int prevented = 0;
01507         uint64_t flags;
01508         dwc_otg_pcd_request_t *req;
01509         dwc_otg_pcd_ep_t *ep;
01510         uint32_t max_transfer;
01511 
01512         ep = get_ep_from_handle(pcd, ep_handle);
01513         if ((!ep->desc && ep->dwc_ep.num != 0)) {
01514                 DWC_WARN("bad ep\n");
01515                 return -DWC_E_INVALID;
01516         }
01517 
01518         if (atomic_alloc) {
01519                 req = dwc_alloc_atomic(sizeof(*req));
01520         } else {
01521                 req = dwc_alloc(sizeof(*req));
01522         }
01523 
01524         if (!req) {
01525                 return -DWC_E_NO_MEMORY;
01526         }
01527         DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
01528         if (!GET_CORE_IF(pcd)->core_params->opt) {
01529                 if (ep->dwc_ep.num != 0) {
01530                         DWC_ERROR("queue req %p, len %d buf %p\n",
01531                                   req_handle, buflen, buf);
01532                 }
01533         }
01534 
01535         req->buf = buf;
01536         req->dma = dma_buf;
01537         req->length = buflen;
01538         req->sent_zlp = zero;
01539         req->priv = req_handle;
01540 
01541         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01542 
01543         /*
01544          * For EP0 IN without premature status, zlp is required?
01545          */
01546         if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
01547                 DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
01548                 //_req->zero = 1;
01549         }
01550 
01551         /* Start the transfer */
01552         if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
01553                 /* EP0 Transfer? */
01554                 if (ep->dwc_ep.num == 0) {
01555                         switch (pcd->ep0state) {
01556                         case EP0_IN_DATA_PHASE:
01557                                 DWC_DEBUGPL(DBG_PCD,
01558                                             "%s ep0: EP0_IN_DATA_PHASE\n",
01559                                             __func__);
01560                                 break;
01561 
01562                         case EP0_OUT_DATA_PHASE:
01563                                 DWC_DEBUGPL(DBG_PCD,
01564                                             "%s ep0: EP0_OUT_DATA_PHASE\n",
01565                                             __func__);
01566                                 if (pcd->request_config) {
01567                                         /* Complete STATUS PHASE */
01568                                         ep->dwc_ep.is_in = 1;
01569                                         pcd->ep0state = EP0_IN_STATUS_PHASE;
01570                                 }
01571                                 break;
01572 
01573                         case EP0_IN_STATUS_PHASE:
01574                                 DWC_DEBUGPL(DBG_PCD,
01575                                             "%s ep0: EP0_IN_STATUS_PHASE\n",
01576                                             __func__);
01577                                 break;
01578 
01579                         default:
01580                                 DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
01581                                             pcd->ep0state);
01582                                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01583                                 return -DWC_E_SHUTDOWN;
01584                         }
01585 
01586                         ep->dwc_ep.dma_addr = dma_buf;
01587                         ep->dwc_ep.start_xfer_buff = buf;
01588                         ep->dwc_ep.xfer_buff = buf;
01589                         ep->dwc_ep.xfer_len = buflen;
01590                         ep->dwc_ep.xfer_count = 0;
01591                         ep->dwc_ep.sent_zlp = 0;
01592                         ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
01593 
01594                         if (zero) {
01595                                 if ((ep->dwc_ep.xfer_len %
01596                                      ep->dwc_ep.maxpacket == 0)
01597                                     && (ep->dwc_ep.xfer_len != 0)) {
01598                                         ep->dwc_ep.sent_zlp = 1;
01599                                 }
01600 
01601                         }
01602 
01603                         dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
01604                                                    &ep->dwc_ep);
01605                 }               // non-ep0 endpoints
01606                 else {
01607 #ifdef DWC_UTE_CFI
01608                         if (ep->dwc_ep.buff_mode != BM_STANDARD) {
01609                                 /* store the request length */
01610                                 ep->dwc_ep.cfi_req_len = buflen;
01611                                 pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
01612                                                                 ep, req);
01613                 } else {
01614 #endif
01615                                 max_transfer =
01616                                     GET_CORE_IF(ep->pcd)->core_params->
01617                                     max_transfer_size;
01618 
01619                         /* Setup and start the Transfer */
01620                         ep->dwc_ep.dma_addr = dma_buf;
01621                         ep->dwc_ep.start_xfer_buff = buf;
01622                         ep->dwc_ep.xfer_buff = buf;
01623                         ep->dwc_ep.xfer_len = 0;
01624                         ep->dwc_ep.xfer_count = 0;
01625                         ep->dwc_ep.sent_zlp = 0;
01626                         ep->dwc_ep.total_len = buflen;
01627 
01628                         ep->dwc_ep.maxxfer = max_transfer;
01629                         if (GET_CORE_IF(pcd)->dma_desc_enable) {
01630                                         uint32_t out_max_xfer =
01631                                             DDMA_MAX_TRANSFER_SIZE -
01632                                             (DDMA_MAX_TRANSFER_SIZE % 4);
01633                                 if (ep->dwc_ep.is_in) {
01634                                         if (ep->dwc_ep.maxxfer >
01635                                             DDMA_MAX_TRANSFER_SIZE) {
01636                                                 ep->dwc_ep.maxxfer =
01637                                                     DDMA_MAX_TRANSFER_SIZE;
01638                                         }
01639                                 } else {
01640                                                 if (ep->dwc_ep.maxxfer >
01641                                                     out_max_xfer) {
01642                                                 ep->dwc_ep.maxxfer =
01643                                                     out_max_xfer;
01644                                         }
01645                                 }
01646                         }
01647                         if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
01648                                 ep->dwc_ep.maxxfer -=
01649                                             (ep->dwc_ep.maxxfer %
01650                                              ep->dwc_ep.maxpacket);
01651                         }
01652 
01653                         if (zero) {
01654                                 if ((ep->dwc_ep.total_len %
01655                                              ep->dwc_ep.maxpacket == 0)
01656                                             && (ep->dwc_ep.total_len != 0)) {
01657                                         ep->dwc_ep.sent_zlp = 1;
01658                                 }
01659                         }
01660 #ifdef DWC_UTE_CFI
01661                         }
01662 #endif
01663                         dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
01664                                                   &ep->dwc_ep);
01665                 }
01666         }
01667 
01668         if ((req != 0) || prevented) {
01669                 ++pcd->request_pending;
01670                 DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
01671                 if (ep->dwc_ep.is_in && ep->stopped
01672                     && !(GET_CORE_IF(pcd)->dma_enable)) {
01674                         diepmsk_data_t diepmsk = {.d32 = 0 };
01675                         diepmsk.b.intktxfemp = 1;
01676                         if (GET_CORE_IF(pcd)->multiproc_int_enable) {
01677                                 dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if->
01678                                                  dev_global_regs->
01679                                                  diepeachintmsk[ep->dwc_ep.num],
01680                                                  0, diepmsk.d32);
01681                         } else {
01682                                 dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if->
01683                                                  dev_global_regs->diepmsk, 0,
01684                                                  diepmsk.d32);
01685                         }
01686 
01687                 }
01688         }
01689 
01690         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01691 
01692         return 0;
01693 }
01694 int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
01695                            void *req_handle)
01696 {
01697         uint64_t flags;
01698         dwc_otg_pcd_request_t *req;
01699         dwc_otg_pcd_ep_t *ep;
01700 
01701         ep = get_ep_from_handle(pcd, ep_handle);
01702         if (!ep->desc && ep->dwc_ep.num != 0) {
01703                 DWC_WARN("bad argument\n");
01704                 return -DWC_E_INVALID;
01705         }
01706 
01707         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01708 
01709         /* make sure it's actually queued on this endpoint */
01710         DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
01711                 if (req->priv == (void *)req_handle) {
01712                         break;
01713                 }
01714         }
01715 
01716         if (req->priv != (void *)req_handle) {
01717                 DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01718                 return -DWC_E_INVALID;
01719         }
01720 
01721         if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
01722                 dwc_otg_request_done(ep, req, -DWC_E_RESTART);
01723         } else {
01724                 req = 0;
01725         }
01726 
01727         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01728 
01729         return req ? 0 : -DWC_E_SHUTDOWN;
01730 
01731 }
01732 
01733 int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
01734 {
01735         dwc_otg_pcd_ep_t *ep;
01736         uint64_t flags;
01737         int retval = 0;
01738 
01739         ep = get_ep_from_handle(pcd, ep_handle);
01740 
01741         if ((!ep->desc && ep != &pcd->ep0) ||
01742             (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
01743                 DWC_WARN("%s, bad ep\n", __func__);
01744                 return -DWC_E_INVALID;
01745         }
01746 
01747         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01748         if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
01749                 DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
01750                          ep->dwc_ep.is_in ? "IN" : "OUT");
01751                 retval = -DWC_E_AGAIN;
01752         } else if (value == 0) {
01753                 dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
01754         } else if (value == 1) {
01755                 if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
01756                         dtxfsts_data_t txstatus;
01757                         fifosize_data_t txfifosize;
01758 
01759                         txfifosize.d32 =
01760                             dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs->
01761                                            dptxfsiz_dieptxf[ep->dwc_ep.
01762                                                             tx_fifo_num]);
01763                         txstatus.d32 =
01764                             dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
01765                                            in_ep_regs[ep->dwc_ep.num]->dtxfsts);
01766 
01767                         if (txstatus.b.txfspcavail < txfifosize.b.depth) {
01768                                 DWC_WARN("%s() Data In Tx Fifo\n", __func__);
01769                                 retval = -DWC_E_AGAIN;
01770                         } else {
01771                                 if (ep->dwc_ep.num == 0) {
01772                                         pcd->ep0state = EP0_STALL;
01773                                 }
01774 
01775                                 ep->stopped = 1;
01776                                 dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
01777                                                      &ep->dwc_ep);
01778                         }
01779                 } else {
01780                         if (ep->dwc_ep.num == 0) {
01781                                 pcd->ep0state = EP0_STALL;
01782                         }
01783 
01784                         ep->stopped = 1;
01785                         dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
01786                 }
01787         } else if (value == 2) {
01788                 ep->dwc_ep.stall_clear_flag = 0;
01789         } else if (value == 3) {
01790                 ep->dwc_ep.stall_clear_flag = 1;
01791         }
01792 
01793         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01794 
01795         return retval;
01796 }
01797 
01801 void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
01802 {
01803         dctl_data_t dctl = { 0 };
01804         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01805         dsts_data_t dsts;
01806 
01807         dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
01808         if (!dsts.b.suspsts) {
01809                 DWC_WARN("Remote wakeup while is not in suspend state\n");
01810         }
01811         /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
01812         if (pcd->remote_wakeup_enable) {
01813                 if (set) {
01814                         dctl.b.rmtwkupsig = 1;
01815                         dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
01816                                          dctl, 0, dctl.d32);
01817                         DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
01818                         dwc_mdelay(2);
01819                         dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
01820                                          dctl, dctl.d32, 0);
01821                         DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
01822                 }
01823         } else {
01824                 DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
01825         }
01826 }
01827 
01828 #ifdef CONFIG_USB_DWC_OTG_LPM
01829 
01832 void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
01833 {
01834         glpmcfg_data_t lpmcfg;
01835         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01836 
01837         lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
01838 
01839         /* Check if we are in L1 state */
01840         if (!lpmcfg.b.prt_sleep_sts) {
01841                 DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
01842                 return;
01843         }
01844 
01845         /* Check if host allows remote wakeup */
01846         if (!lpmcfg.b.rem_wkup_en) {
01847                 DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
01848                 return;
01849         }
01850 
01851         /* Check if Resume OK */
01852         if (!lpmcfg.b.sleep_state_resumeok) {
01853                 DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
01854                 return;
01855         }
01856 
01857         lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
01858         lpmcfg.b.en_utmi_sleep = 0;
01859         lpmcfg.b.hird_thres &= (~(1 << 4));
01860         dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
01861 
01862         if (set) {
01863                 dctl_data_t dctl = {.d32 = 0 };
01864                 dctl.b.rmtwkupsig = 1;
01865                 /* Set RmtWkUpSig bit to start remote wakup signaling.
01866                  * Hardware will automatically clear this bit.
01867                  */
01868                 dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl,
01869                                  0, dctl.d32);
01870                 DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
01871         }
01872 
01873 }
01874 #endif
01875 
01879 void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
01880 {
01881         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
01882         if (dwc_otg_is_device_mode(core_if)) {
01883 #ifdef CONFIG_USB_DWC_OTG_LPM
01884                 if (core_if->lx_state == DWC_OTG_L1) {
01885                         dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
01886                 } else {
01887 #endif
01888                         dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
01889 #ifdef CONFIG_USB_DWC_OTG_LPM
01890                 }
01891 #endif
01892         }
01893         return;
01894 }
01895 
01896 int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
01897 {
01898         dsts_data_t dsts;
01899         gotgctl_data_t gotgctl;
01900         uint64_t flags;
01901 
01902         DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
01903 
01904         /*
01905          * This function starts the Protocol if no session is in progress. If
01906          * a session is already in progress, but the device is suspended,
01907          * remote wakeup signaling is started.
01908          */
01909 
01910         /* Check if valid session */
01911         gotgctl.d32 =
01912             dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
01913         if (gotgctl.b.bsesvld) {
01914                 /* Check if suspend state */
01915                 dsts.d32 =
01916                     dwc_read_reg32(&
01917                                    (GET_CORE_IF(pcd)->dev_if->dev_global_regs->
01918                                     dsts));
01919                 if (dsts.b.suspsts) {
01920                         dwc_otg_pcd_remote_wakeup(pcd, 1);
01921                 }
01922         } else {
01923                 dwc_otg_pcd_initiate_srp(pcd);
01924         }
01925 
01926         DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
01927         return 0;
01928 
01929 }
01930 
01937 void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t * pcd)
01938 {
01939         GET_CORE_IF(pcd)->srp_timer_started = 1;
01940         DWC_TIMER_SCHEDULE(pcd->srp_timer, 6000 /* 6 secs */ );
01941 }
01942 
01943 void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
01944 {
01945         uint32_t *addr =
01946             (uint32_t *) & (GET_CORE_IF(pcd)->core_global_regs->gotgctl);
01947         gotgctl_data_t mem;
01948         gotgctl_data_t val;
01949 
01950         val.d32 = dwc_read_reg32(addr);
01951         if (val.b.sesreq) {
01952                 DWC_ERROR("Session Request Already active!\n");
01953                 return;
01954         }
01955 
01956         DWC_INFO("Session Request Initated\n"); //NOTICE
01957         mem.d32 = dwc_read_reg32(addr);
01958         mem.b.sesreq = 1;
01959         dwc_write_reg32(addr, mem.d32);
01960 
01961         /* Start the SRP timer */
01962         dwc_otg_pcd_start_srp_timer(pcd);
01963         return;
01964 }
01965 
01966 int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
01967 {
01968         return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
01969 }
01970 
01971 int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
01972 {
01973         return GET_CORE_IF(pcd)->core_params->lpm_enable;
01974 }
01975 
01976 uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
01977 {
01978         return pcd->b_hnp_enable;
01979 }
01980 
01981 uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
01982 {
01983         return pcd->a_hnp_support;
01984 }
01985 
01986 uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
01987 {
01988         return pcd->a_alt_hnp_support;
01989 }
01990 
01991 int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
01992 {
01993         return pcd->remote_wakeup_enable;
01994 }
01995 
01996 #endif                          /* DWC_HOST_ONLY */

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