00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00090 ep->stopped = 1;
00091
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
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
00138
00139 if (dwc_otg_is_device_mode(core_if)) {
00140 dwc_otg_core_dev_init(core_if);
00141
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
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,
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
00569
00570
00571
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
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
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
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
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
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
00913 pcd_ep->desc = 0;
00914 pcd_ep->pcd = pcd;
00915 pcd_ep->stopped = 1;
00916 pcd_ep->queue_sof = 0;
00917
00918
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
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 , 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 , 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
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
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
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
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
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
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
01146
01147
01148 if (dwc_otg_is_device_mode(core_if) ) {
01149 dwc_otg_core_dev_init(core_if);
01150 }
01151
01152
01153
01154
01155 dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
01156
01157
01158
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
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
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
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
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
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
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
01538
01539 ep->dwc_ep.tx_fifo_num =
01540 assign_perio_tx_fifo(GET_CORE_IF(pcd));
01541 }
01542 } else {
01543
01544
01545
01546 ep->dwc_ep.tx_fifo_num =
01547 assign_tx_fifo(GET_CORE_IF(pcd));
01548 }
01549
01550
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
01568 if (ep->dwc_ep.type == UE_BULK) {
01569 ep->dwc_ep.data_pid_start = 0;
01570 }
01571
01572
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
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
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
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
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
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
01754 for (i = 0; i < ereq->pio_pkt_count; i++) {
01755
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
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
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
01795 for (i = 0; i < ereq->pio_pkt_count; i++) {
01796
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
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
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
01854 dwcep = &ep->dwc_ep;
01855
01856
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
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
01882 for (i = 0; i < ereq->pio_pkt_count; i++) {
01883 if (dwcep->is_in) {
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 {
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
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
01905 dwc_pcd_xiso_ereq_free(ep, req);
01906
01907
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;
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
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
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
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;
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
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
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
02021
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
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
02049 DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
02050 ep->dwc_ep.xiso_queued_xfers++;
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
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
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
02125
02126
02127
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
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
02153 }
02154
02155
02156 if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
02157
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
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 }
02210 else {
02211 #ifdef DWC_UTE_CFI
02212 if (ep->dwc_ep.buff_mode != BM_STANDARD) {
02213
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
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
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
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
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
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
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
02481 if (!lpmcfg.b.prt_sleep_sts) {
02482 DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
02483 return;
02484 }
02485
02486
02487 if (!lpmcfg.b.rem_wkup_en) {
02488 DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
02489 return;
02490 }
02491
02492
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
02507
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
02566
02567
02568
02569
02570
02571 gotgctl.d32 =
02572 DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
02573 if (gotgctl.b.bsesvld) {
02574
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