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
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
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
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
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
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,
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
00546
00547
00548
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
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
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
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
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
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
00883 pcd_ep->desc = 0;
00884 pcd_ep->pcd = pcd;
00885 pcd_ep->stopped = 1;
00886 pcd_ep->queue_sof = 0;
00887
00888
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
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 , 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 , 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
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
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
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
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
01087
01088 if (dwc_otg_is_device_mode(core_if)) {
01089 dwc_otg_core_dev_init(core_if);
01090 }
01091
01092
01093
01094
01095 dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
01096
01097
01098
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
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
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
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
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
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
01396
01397 ep->dwc_ep.tx_fifo_num =
01398 assign_perio_tx_fifo(GET_CORE_IF(pcd));
01399 }
01400 } else {
01401
01402
01403
01404 ep->dwc_ep.tx_fifo_num =
01405 assign_tx_fifo(GET_CORE_IF(pcd));
01406
01407 }
01408 }
01409
01410 if (ep->dwc_ep.type == UE_BULK) {
01411 ep->dwc_ep.data_pid_start = 0;
01412 }
01413
01414
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
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
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
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
01549 }
01550
01551
01552 if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
01553
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
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 }
01606 else {
01607 #ifdef DWC_UTE_CFI
01608 if (ep->dwc_ep.buff_mode != BM_STANDARD) {
01609
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
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
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
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
01840 if (!lpmcfg.b.prt_sleep_sts) {
01841 DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
01842 return;
01843 }
01844
01845
01846 if (!lpmcfg.b.rem_wkup_en) {
01847 DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
01848 return;
01849 }
01850
01851
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
01866
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
01906
01907
01908
01909
01910
01911 gotgctl.d32 =
01912 dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
01913 if (gotgctl.b.bsesvld) {
01914
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 );
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");
01957 mem.d32 = dwc_read_reg32(addr);
01958 mem.b.sesreq = 1;
01959 dwc_write_reg32(addr, mem.d32);
01960
01961
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