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
00035 #ifdef DWC_UTE_CFI
00036
00037 #include "dwc_otg_pcd.h"
00038 #include "dwc_otg_cfi.h"
00039
00041 #define DWC_CONSTANT_CPU_TO_LE16(x) (x)
00042
00043 extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
00044
00045 static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
00046 static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
00047 struct dwc_otg_pcd *pcd,
00048 struct cfi_usb_ctrlrequest *ctrl_req);
00049 static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
00050 static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00051 struct cfi_usb_ctrlrequest *req);
00052 static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00053 struct cfi_usb_ctrlrequest *req);
00054 static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00055 struct cfi_usb_ctrlrequest *req);
00056 static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
00057 struct cfi_usb_ctrlrequest *req);
00058 static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
00059
00060 static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
00061 static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
00062 static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
00063
00064 static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
00065
00067 static cfi_all_features_header_t all_props_desc_header = {
00068 .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
00069 .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
00070 .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
00071 };
00072
00074 static cfi_feature_desc_header_t prop_descs[] = {
00075
00076
00077 {
00078 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
00079 .bmAttributes = CFI_FEATURE_ATTR_RW,
00080 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
00081 },
00082
00083
00084 {
00085 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
00086 .bmAttributes = CFI_FEATURE_ATTR_RW,
00087 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00088 },
00089
00090
00091 {
00092 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
00093 .bmAttributes = CFI_FEATURE_ATTR_RW,
00094 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00095 },
00096
00097
00098 {
00099 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
00100 .bmAttributes = CFI_FEATURE_ATTR_RW,
00101
00102 },
00103
00104
00105 {
00106 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
00107 .bmAttributes = CFI_FEATURE_ATTR_RW,
00108 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00109 },
00110
00111
00112 {
00113 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
00114 .bmAttributes = CFI_FEATURE_ATTR_RW,
00115 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00116 },
00117
00118
00119 {
00120 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
00121 .bmAttributes = CFI_FEATURE_ATTR_RO,
00122 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00123 },
00124
00125
00126 {
00127 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
00128 .bmAttributes = CFI_FEATURE_ATTR_RW,
00129 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00130 },
00131
00132
00133 {
00134 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
00135 .bmAttributes = CFI_FEATURE_ATTR_RW,
00136 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00137 }
00138 };
00139
00141 cfi_string_t prop_name_table[] = {
00142 {FT_ID_DMA_MODE, "dma_mode"},
00143 {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
00144 {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
00145 {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
00146 {FT_ID_DMA_CIRCULAR, "buffer_circular"},
00147 {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
00148 {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
00149 {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
00150 {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
00151 {}
00152 };
00153
00154
00155
00161 const uint8_t *get_prop_name(uint16_t prop_id, int *len)
00162 {
00163 cfi_string_t *pstr;
00164 *len = 0;
00165
00166 for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
00167 if (pstr->id == prop_id) {
00168 *len = DWC_STRLEN(pstr->s);
00169 return pstr->s;
00170 }
00171 }
00172 return NULL;
00173 }
00174
00180 int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
00181 {
00182 int retval = 0;
00183 dwc_otg_pcd_ep_t *ep = NULL;
00184 cfiobject_t *cfi = pcd->cfi;
00185 struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
00186 uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
00187 uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
00188 uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
00189 uint32_t regaddr = 0;
00190 uint32_t regval = 0;
00191
00192
00193
00194
00195 cfi->ctrl_req = *ctrl;
00196 cfi->ctrl_req.data = NULL;
00197
00198 cfi->need_gadget_att = 0;
00199 cfi->need_status_in_complete = 0;
00200
00201 switch (ctrl->bRequest) {
00202 case VEN_CORE_GET_FEATURES:
00203 retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
00204 if (retval >= 0) {
00205
00206 ep = &pcd->ep0;
00207
00208 retval = min((uint16_t) retval, wLen);
00209
00210 ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00211 ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00212 ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00213 ep->dwc_ep.xfer_len = retval;
00214 ep->dwc_ep.xfer_count = 0;
00215 ep->dwc_ep.sent_zlp = 0;
00216 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00217
00218 pcd->ep0_pending = 1;
00219 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00220 }
00221 retval = 0;
00222 break;
00223
00224 case VEN_CORE_GET_FEATURE:
00225 CFI_INFO("VEN_CORE_GET_FEATURE\n");
00226 retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
00227 pcd, ctrl);
00228 if (retval >= 0) {
00229 ep = &pcd->ep0;
00230
00231 retval = min((uint16_t) retval, wLen);
00232
00233 ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00234 ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00235 ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00236 ep->dwc_ep.xfer_len = retval;
00237 ep->dwc_ep.xfer_count = 0;
00238 ep->dwc_ep.sent_zlp = 0;
00239 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00240
00241 pcd->ep0_pending = 1;
00242 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00243 }
00244 CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
00245 dump_msg(cfi->buf_in.buf, retval);
00246 break;
00247
00248 case VEN_CORE_SET_FEATURE:
00249 CFI_INFO("VEN_CORE_SET_FEATURE\n");
00250
00251
00252
00253 ep = &pcd->ep0;
00254 ep->dwc_ep.is_in = 0;
00255 ep->dwc_ep.dma_addr = cfi->buf_out.addr;
00256 ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
00257 ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
00258 ep->dwc_ep.xfer_len = wLen;
00259 ep->dwc_ep.xfer_count = 0;
00260 ep->dwc_ep.sent_zlp = 0;
00261 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00262
00263 pcd->ep0_pending = 1;
00264
00265 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00266 retval = 0;
00267 break;
00268
00269 case VEN_CORE_RESET_FEATURES:
00270 CFI_INFO("VEN_CORE_RESET_FEATURES\n");
00271 cfi->need_gadget_att = 1;
00272 cfi->need_status_in_complete = 1;
00273 retval = cfi_preproc_reset(pcd, ctrl);
00274 CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
00275 break;
00276
00277 case VEN_CORE_ACTIVATE_FEATURES:
00278 CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
00279 break;
00280
00281 case VEN_CORE_READ_REGISTER:
00282 CFI_INFO("VEN_CORE_READ_REGISTER\n");
00283
00284
00285
00286 if (wValue == 0) {
00287
00288 regaddr = 0;
00289
00290
00291 regaddr |= wIndex;
00292 } else {
00293 regaddr = (wValue << 16) | wIndex;
00294 }
00295
00296
00297 regval = DWC_READ_REG32((uint32_t *) regaddr);
00298
00299 ep = &pcd->ep0;
00300 dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t));
00301 ep->dwc_ep.is_in = 1;
00302 ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00303 ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00304 ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00305 ep->dwc_ep.xfer_len = wLen;
00306 ep->dwc_ep.xfer_count = 0;
00307 ep->dwc_ep.sent_zlp = 0;
00308 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00309
00310 pcd->ep0_pending = 1;
00311 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00312 cfi->need_gadget_att = 0;
00313 retval = 0;
00314 break;
00315
00316 case VEN_CORE_WRITE_REGISTER:
00317 CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
00318
00319
00320
00321 ep = &pcd->ep0;
00322 ep->dwc_ep.is_in = 0;
00323 ep->dwc_ep.dma_addr = cfi->buf_out.addr;
00324 ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
00325 ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
00326 ep->dwc_ep.xfer_len = wLen;
00327 ep->dwc_ep.xfer_count = 0;
00328 ep->dwc_ep.sent_zlp = 0;
00329 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00330
00331 pcd->ep0_pending = 1;
00332
00333 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00334 retval = 0;
00335 break;
00336
00337 default:
00338 retval = -DWC_E_NOT_SUPPORTED;
00339 break;
00340 }
00341
00342 return retval;
00343 }
00344
00356 static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
00357 {
00358 cfi_feature_desc_header_t *prop_hdr = prop_descs;
00359 cfi_feature_desc_header_t *prop;
00360 cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
00361 cfi_all_features_header_t *tmp;
00362 uint8_t *tmpbuf = buf;
00363 const uint8_t *pname = NULL;
00364 int i, j, namelen = 0, totlen;
00365
00366
00367 CFI_INFO("%s:\n", __func__);
00368
00369 tmp = (cfi_all_features_header_t *) tmpbuf;
00370 *tmp = *all_props_hdr;
00371 tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
00372
00373 j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
00374 for (i = 0; i < j; i++, prop_hdr++) {
00375 pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
00376 prop = (cfi_feature_desc_header_t *) tmpbuf;
00377 *prop = *prop_hdr;
00378
00379 prop->bNameLen = namelen;
00380 prop->wLength =
00381 DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
00382 namelen);
00383
00384 tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
00385 dwc_memcpy(tmpbuf, pname, namelen);
00386 tmpbuf += namelen;
00387 }
00388
00389 totlen = tmpbuf - buf;
00390
00391 if (totlen > 0) {
00392 tmp = (cfi_all_features_header_t *) buf;
00393 tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
00394 }
00395
00396 return totlen;
00397 }
00398
00402 static void cfi_release(cfiobject_t * cfiobj)
00403 {
00404 cfi_ep_t *cfiep;
00405 dwc_list_link_t *tmp;
00406
00407 CFI_INFO("%s\n", __func__);
00408
00409 if (cfiobj->buf_in.buf) {
00410 DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
00411 cfiobj->buf_in.addr);
00412 cfiobj->buf_in.buf = NULL;
00413 }
00414
00415 if (cfiobj->buf_out.buf) {
00416 DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
00417 cfiobj->buf_out.addr);
00418 cfiobj->buf_out.buf = NULL;
00419 }
00420
00421
00422
00423 DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
00424 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
00425 cfi_free_ep_bs_dyn_data(cfiep);
00426 }
00427 }
00428
00432 static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
00433 {
00434 if (cfiep->bm_sg) {
00435 DWC_FREE(cfiep->bm_sg);
00436 cfiep->bm_sg = NULL;
00437 }
00438
00439 if (cfiep->bm_align) {
00440 DWC_FREE(cfiep->bm_align);
00441 cfiep->bm_align = NULL;
00442 }
00443
00444 if (cfiep->bm_concat) {
00445 if (NULL != cfiep->bm_concat->wTxBytes) {
00446 DWC_FREE(cfiep->bm_concat->wTxBytes);
00447 cfiep->bm_concat->wTxBytes = NULL;
00448 }
00449 DWC_FREE(cfiep->bm_concat);
00450 cfiep->bm_concat = NULL;
00451 }
00452 }
00453
00459 static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
00460 {
00461 int retval = 0;
00462
00463 cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
00464 if (NULL == cfiep->bm_sg) {
00465 CFI_INFO("Failed to allocate memory for SG feature value\n");
00466 return -DWC_E_NO_MEMORY;
00467 }
00468 dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00469
00470
00471
00472
00473
00474 cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
00475 if (NULL == cfiep->bm_concat) {
00476 CFI_INFO
00477 ("Failed to allocate memory for CONCATENATION feature value\n");
00478 DWC_FREE(cfiep->bm_sg);
00479 return -DWC_E_NO_MEMORY;
00480 }
00481 dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
00482
00483 cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
00484 if (NULL == cfiep->bm_align) {
00485 CFI_INFO
00486 ("Failed to allocate memory for Alignment feature value\n");
00487 DWC_FREE(cfiep->bm_sg);
00488 DWC_FREE(cfiep->bm_concat);
00489 return -DWC_E_NO_MEMORY;
00490 }
00491 dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
00492
00493 return retval;
00494 }
00495
00507 static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
00508 struct dwc_otg_pcd_ep *ep)
00509 {
00510 cfi_ep_t *cfiep;
00511 int retval = -DWC_E_NOT_SUPPORTED;
00512
00513 CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
00514 "EP_" , ep->desc->bEndpointAddress);
00515
00516 cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
00517
00518 if (NULL == cfiep) {
00519
00520 cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
00521 if (NULL == cfiep) {
00522 CFI_INFO
00523 ("Unable to allocate memory for <cfiep> in function %s\n",
00524 __func__);
00525 return -DWC_E_NO_MEMORY;
00526 }
00527 dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
00528
00529
00530 cfiep->ep = ep;
00531
00532
00533 ep->dwc_ep.descs =
00534 DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
00535 sizeof(dwc_otg_dma_desc_t),
00536 &ep->dwc_ep.descs_dma_addr);
00537
00538 if (NULL == ep->dwc_ep.descs) {
00539 DWC_FREE(cfiep);
00540 return -DWC_E_NO_MEMORY;
00541 }
00542
00543 DWC_LIST_INIT(&cfiep->lh);
00544
00545
00546
00547 ep->dwc_ep.buff_mode = BM_STANDARD;
00548
00549
00550 if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
00551 return retval;
00552
00553
00554 DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
00555 retval = 0;
00556 } else {
00557 CFI_INFO("%s: The sought EP already is in the list\n",
00558 __func__);
00559 }
00560
00561 return retval;
00562 }
00563
00569 static int cfi_ctrl_write_complete(struct cfiobject *cfi,
00570 struct dwc_otg_pcd *pcd)
00571 {
00572 uint32_t addr, reg_value;
00573 uint16_t wIndex, wValue;
00574 uint8_t bRequest;
00575 uint8_t *buf = cfi->buf_out.buf;
00576
00577 struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
00578 int retval = -DWC_E_NOT_SUPPORTED;
00579
00580 CFI_INFO("%s\n", __func__);
00581
00582 bRequest = ctrl_req->bRequest;
00583 wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
00584 wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
00585
00586
00587
00588
00589
00590 ctrl_req->data = cfi->buf_out.buf;
00591 cfi->need_status_in_complete = 0;
00592 cfi->need_gadget_att = 0;
00593
00594 switch (bRequest) {
00595 case VEN_CORE_WRITE_REGISTER:
00596
00597 reg_value = *((uint32_t *) buf);
00598 if (wValue == 0) {
00599 addr = 0;
00600
00601 addr += wIndex;
00602 } else {
00603 addr = (wValue << 16) | wIndex;
00604 }
00605
00606
00607
00608 retval = 0;
00609 cfi->need_status_in_complete = 1;
00610 break;
00611
00612 case VEN_CORE_SET_FEATURE:
00613
00614 retval = cfi_set_feature_value(pcd);
00615 if (retval < 0)
00616 return retval;
00617
00618 cfi->need_status_in_complete = 1;
00619 break;
00620
00621 default:
00622 break;
00623 }
00624
00625 return retval;
00626 }
00627
00631 static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00632 dwc_otg_pcd_request_t * req)
00633 {
00634 struct dwc_otg_pcd_ep *ep = cfiep->ep;
00635 ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
00636 struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00637 struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
00638 dma_addr_t buff_addr = req->dma;
00639 int i;
00640 uint32_t txsize, off;
00641
00642 txsize = sgval->wSize;
00643 off = sgval->bOffset;
00644
00645
00646
00647
00648 for (i = 0; i < sgval->bCount; i++) {
00649 desc->status.b.bs = BS_HOST_BUSY;
00650 desc->buf = buff_addr;
00651 desc->status.b.l = 0;
00652 desc->status.b.ioc = 0;
00653 desc->status.b.sp = 0;
00654 desc->status.b.bytes = txsize;
00655 desc->status.b.bs = BS_HOST_READY;
00656
00657
00658 buff_addr += txsize + off;
00659 desc_last = desc;
00660 desc++;
00661 }
00662
00663
00664 desc_last->status.b.l = 1;
00665 desc_last->status.b.ioc = 1;
00666 desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
00667
00668 cfiep->dma_desc_last = desc_last;
00669 cfiep->desc_count = sgval->bCount;
00670 }
00671
00675 static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00676 dwc_otg_pcd_request_t * req)
00677 {
00678 struct dwc_otg_pcd_ep *ep = cfiep->ep;
00679 ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
00680 struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00681 struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
00682 dma_addr_t buff_addr = req->dma;
00683 int i;
00684 uint16_t *txsize;
00685
00686 txsize = concatval->wTxBytes;
00687
00688 for (i = 0; i < concatval->hdr.bDescCount; i++) {
00689 desc->buf = buff_addr;
00690 desc->status.b.bs = BS_HOST_BUSY;
00691 desc->status.b.l = 0;
00692 desc->status.b.ioc = 0;
00693 desc->status.b.sp = 0;
00694 desc->status.b.bytes = *txsize;
00695 desc->status.b.bs = BS_HOST_READY;
00696
00697 txsize++;
00698
00699 buff_addr += UGETW(ep->desc->wMaxPacketSize);
00700 desc_last = desc;
00701 desc++;
00702 }
00703
00704
00705 desc_last->status.b.l = 1;
00706 desc_last->status.b.ioc = 1;
00707 desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
00708 cfiep->dma_desc_last = desc_last;
00709 cfiep->desc_count = concatval->hdr.bDescCount;
00710 }
00711
00715 static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00716 dwc_otg_pcd_request_t * req)
00717 {
00718
00719 }
00720
00724 static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00725 dwc_otg_pcd_request_t * req)
00726 {
00727 struct dwc_otg_pcd_ep *ep = cfiep->ep;
00728 ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
00729 struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00730 dma_addr_t buff_addr = req->dma;
00731
00732 desc->status.b.bs = BS_HOST_BUSY;
00733 desc->status.b.l = 1;
00734 desc->status.b.ioc = 1;
00735 desc->status.b.sp = ep->dwc_ep.sent_zlp;
00736 desc->status.b.bytes = req->length;
00737
00738 desc->buf = (buff_addr + alignval->bAlign);
00739 desc->status.b.bs = BS_HOST_READY;
00740 cfiep->dma_desc_last = desc;
00741 cfiep->desc_count = 1;
00742 }
00743
00748 static void cfi_build_descriptors(struct cfiobject *cfi,
00749 struct dwc_otg_pcd *pcd,
00750 struct dwc_otg_pcd_ep *ep,
00751 dwc_otg_pcd_request_t * req)
00752 {
00753 cfi_ep_t *cfiep;
00754
00755
00756 cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
00757 if (NULL == cfiep) {
00758 CFI_INFO("%s: Unable to find a matching active endpoint\n",
00759 __func__);
00760 return;
00761 }
00762
00763 cfiep->xfer_len = req->length;
00764
00765
00766 switch (cfiep->ep->dwc_ep.buff_mode) {
00767 case BM_SG:
00768 cfi_build_sg_descs(cfi, cfiep, req);
00769 break;
00770
00771 case BM_CONCAT:
00772 cfi_build_concat_descs(cfi, cfiep, req);
00773 break;
00774
00775 case BM_CIRCULAR:
00776 cfi_build_circ_descs(cfi, cfiep, req);
00777 break;
00778
00779 case BM_ALIGN:
00780 cfi_build_align_descs(cfi, cfiep, req);
00781 break;
00782
00783 default:
00784 break;
00785 }
00786 }
00787
00791 static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
00792 struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
00793 unsigned size, gfp_t flags)
00794 {
00795 return DWC_DMA_ALLOC(size, dma);
00796 }
00797
00801 int init_cfi(cfiobject_t * cfiobj)
00802 {
00803 CFI_INFO("%s\n", __func__);
00804
00805
00806 cfiobj->buf_in.buf =
00807 DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
00808 if (NULL == cfiobj->buf_in.buf) {
00809 CFI_INFO("Unable to allocate buffer for INs\n");
00810 return -DWC_E_NO_MEMORY;
00811 }
00812
00813
00814 cfiobj->buf_out.buf =
00815 DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
00816 if (NULL == cfiobj->buf_out.buf) {
00817 CFI_INFO("Unable to allocate buffer for OUT\n");
00818 return -DWC_E_NO_MEMORY;
00819 }
00820
00821
00822 cfiobj->ops.release = cfi_release;
00823 cfiobj->ops.ep_enable = cfi_ep_enable;
00824 cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
00825 cfiobj->ops.build_descriptors = cfi_build_descriptors;
00826 cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
00827
00828
00829 DWC_LIST_INIT(&cfiobj->active_eps);
00830
00831 return 0;
00832 }
00833
00839 static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
00840 struct dwc_otg_pcd *pcd,
00841 struct cfi_usb_ctrlrequest *ctrl_req)
00842 {
00843 int retval = -DWC_E_NOT_SUPPORTED;
00844 struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
00845 uint16_t dfifo, rxfifo, txfifo;
00846
00847 switch (ctrl_req->wIndex) {
00848
00849 case FT_ID_DMA_MODE:
00850 *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
00851 retval = 1;
00852 break;
00853
00854 case FT_ID_DMA_BUFFER_SETUP:
00855 retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
00856 break;
00857
00858 case FT_ID_DMA_BUFF_ALIGN:
00859 retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
00860 break;
00861
00862 case FT_ID_DMA_CONCAT_SETUP:
00863 retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
00864 break;
00865
00866 case FT_ID_DMA_CIRCULAR:
00867 CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
00868 break;
00869
00870 case FT_ID_THRESHOLD_SETUP:
00871 CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
00872 break;
00873
00874 case FT_ID_DFIFO_DEPTH:
00875 dfifo = get_dfifo_size(coreif);
00876 *((uint16_t *) buf) = dfifo;
00877 retval = sizeof(uint16_t);
00878 break;
00879
00880 case FT_ID_TX_FIFO_DEPTH:
00881 retval = get_txfifo_size(pcd, ctrl_req->wValue);
00882 if (retval >= 0) {
00883 txfifo = retval;
00884 *((uint16_t *) buf) = txfifo;
00885 retval = sizeof(uint16_t);
00886 }
00887 break;
00888
00889 case FT_ID_RX_FIFO_DEPTH:
00890 retval = get_rxfifo_size(coreif, ctrl_req->wValue);
00891 if (retval >= 0) {
00892 rxfifo = retval;
00893 *((uint16_t *) buf) = rxfifo;
00894 retval = sizeof(uint16_t);
00895 }
00896 break;
00897 }
00898
00899 return retval;
00900 }
00901
00905 static int cfi_reset_sg_val(cfi_ep_t * cfiep)
00906 {
00907 dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00908 return 0;
00909 }
00910
00914 static int cfi_reset_align_val(cfi_ep_t * cfiep)
00915 {
00916 dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00917 return 0;
00918 }
00919
00925 static int cfi_reset_concat_val(cfi_ep_t * cfiep)
00926 {
00927
00928 if (cfiep->bm_concat->wTxBytes) {
00929 DWC_FREE(cfiep->bm_concat->wTxBytes);
00930 cfiep->bm_concat->wTxBytes = NULL;
00931 }
00932
00933 dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
00934 return 0;
00935 }
00936
00940 static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
00941 {
00942 cfi_reset_sg_val(cfiep);
00943 cfi_reset_align_val(cfiep);
00944 cfi_reset_concat_val(cfiep);
00945 return 0;
00946 }
00947
00948 static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
00949 uint8_t rx_rst, uint8_t tx_rst)
00950 {
00951 int retval = -DWC_E_INVALID;
00952 uint16_t tx_siz[15];
00953 uint16_t rx_siz = 0;
00954 dwc_otg_pcd_ep_t *ep = NULL;
00955 dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00956 dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
00957
00958 if (rx_rst) {
00959 rx_siz = params->dev_rx_fifo_size;
00960 params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
00961 }
00962
00963 if (tx_rst) {
00964 if (ep_addr == 0) {
00965 int i;
00966
00967 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
00968 tx_siz[i] =
00969 core_if->core_params->dev_tx_fifo_size[i];
00970 core_if->core_params->dev_tx_fifo_size[i] =
00971 core_if->init_txfsiz[i];
00972 }
00973 } else {
00974
00975 ep = get_ep_by_addr(pcd, ep_addr);
00976
00977 if (NULL == ep) {
00978 CFI_INFO
00979 ("%s: Unable to get the endpoint addr=0x%02x\n",
00980 __func__, ep_addr);
00981 return -DWC_E_INVALID;
00982 }
00983
00984 tx_siz[0] =
00985 params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
00986 1];
00987 params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
00988 GET_CORE_IF(pcd)->init_txfsiz[ep->
00989 dwc_ep.tx_fifo_num -
00990 1];
00991 }
00992 }
00993
00994 if (resize_fifos(GET_CORE_IF(pcd))) {
00995 retval = 0;
00996 } else {
00997 CFI_INFO
00998 ("%s: Error resetting the feature Reset All(FIFO size)\n",
00999 __func__);
01000 if (rx_rst) {
01001 params->dev_rx_fifo_size = rx_siz;
01002 }
01003
01004 if (tx_rst) {
01005 if (ep_addr == 0) {
01006 int i;
01007 for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
01008 i++) {
01009 core_if->
01010 core_params->dev_tx_fifo_size[i] =
01011 tx_siz[i];
01012 }
01013 } else {
01014 params->dev_tx_fifo_size[ep->
01015 dwc_ep.tx_fifo_num -
01016 1] = tx_siz[0];
01017 }
01018 }
01019 retval = -DWC_E_INVALID;
01020 }
01021 return retval;
01022 }
01023
01024 static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
01025 {
01026 int retval = 0;
01027 cfi_ep_t *cfiep;
01028 cfiobject_t *cfi = pcd->cfi;
01029 dwc_list_link_t *tmp;
01030
01031 retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
01032 if (retval < 0) {
01033 return retval;
01034 }
01035
01036
01037 if (addr) {
01038 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01039 if (NULL == cfiep) {
01040 CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01041 __func__, addr);
01042 return -DWC_E_INVALID;
01043 }
01044 retval = cfi_ep_reset_all_setup_vals(cfiep);
01045 cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
01046 }
01047
01048 else {
01049
01050
01051 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01052 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01053 retval = cfi_ep_reset_all_setup_vals(cfiep);
01054 cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
01055 if (retval < 0) {
01056 CFI_INFO
01057 ("%s: Error resetting the feature Reset All\n",
01058 __func__);
01059 return retval;
01060 }
01061 }
01062 }
01063 return retval;
01064 }
01065
01066 static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
01067 uint8_t addr)
01068 {
01069 int retval = 0;
01070 cfi_ep_t *cfiep;
01071 cfiobject_t *cfi = pcd->cfi;
01072 dwc_list_link_t *tmp;
01073
01074
01075 if (addr) {
01076 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01077 if (NULL == cfiep) {
01078 CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01079 __func__, addr);
01080 return -DWC_E_INVALID;
01081 }
01082 retval = cfi_reset_sg_val(cfiep);
01083 }
01084
01085 else {
01086
01087
01088 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01089 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01090 retval = cfi_reset_sg_val(cfiep);
01091 if (retval < 0) {
01092 CFI_INFO
01093 ("%s: Error resetting the feature Buffer Setup\n",
01094 __func__);
01095 return retval;
01096 }
01097 }
01098 }
01099 return retval;
01100 }
01101
01102 static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
01103 {
01104 int retval = 0;
01105 cfi_ep_t *cfiep;
01106 cfiobject_t *cfi = pcd->cfi;
01107 dwc_list_link_t *tmp;
01108
01109
01110 if (addr) {
01111 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01112 if (NULL == cfiep) {
01113 CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01114 __func__, addr);
01115 return -DWC_E_INVALID;
01116 }
01117 retval = cfi_reset_concat_val(cfiep);
01118 }
01119
01120 else {
01121
01122
01123 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01124 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01125 retval = cfi_reset_concat_val(cfiep);
01126 if (retval < 0) {
01127 CFI_INFO
01128 ("%s: Error resetting the feature Concatenation Value\n",
01129 __func__);
01130 return retval;
01131 }
01132 }
01133 }
01134 return retval;
01135 }
01136
01137 static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
01138 {
01139 int retval = 0;
01140 cfi_ep_t *cfiep;
01141 cfiobject_t *cfi = pcd->cfi;
01142 dwc_list_link_t *tmp;
01143
01144
01145 if (addr) {
01146 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01147 if (NULL == cfiep) {
01148 CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01149 __func__, addr);
01150 return -DWC_E_INVALID;
01151 }
01152 retval = cfi_reset_align_val(cfiep);
01153 }
01154
01155 else {
01156
01157
01158 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01159 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01160 retval = cfi_reset_align_val(cfiep);
01161 if (retval < 0) {
01162 CFI_INFO
01163 ("%s: Error resetting the feature Aliignment Value\n",
01164 __func__);
01165 return retval;
01166 }
01167 }
01168 }
01169 return retval;
01170
01171 }
01172
01173 static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
01174 struct cfi_usb_ctrlrequest *req)
01175 {
01176 int retval = 0;
01177
01178 switch (req->wIndex) {
01179 case 0:
01180
01181 retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
01182 break;
01183
01184 case FT_ID_DMA_BUFFER_SETUP:
01185
01186 retval =
01187 cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
01188 break;
01189
01190 case FT_ID_DMA_CONCAT_SETUP:
01191
01192 retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
01193 break;
01194
01195 case FT_ID_DMA_BUFF_ALIGN:
01196
01197 retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
01198 break;
01199
01200 case FT_ID_TX_FIFO_DEPTH:
01201 retval =
01202 cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
01203 pcd->cfi->need_gadget_att = 0;
01204 break;
01205
01206 case FT_ID_RX_FIFO_DEPTH:
01207 retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
01208 pcd->cfi->need_gadget_att = 0;
01209 break;
01210 default:
01211 break;
01212 }
01213 return retval;
01214 }
01215
01219 static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01220 {
01221 uint8_t inaddr, outaddr;
01222 cfi_ep_t *epin, *epout;
01223 ddma_sg_buffer_setup_t *psgval;
01224 uint32_t desccount, size;
01225
01226 CFI_INFO("%s\n", __func__);
01227
01228 psgval = (ddma_sg_buffer_setup_t *) buf;
01229 desccount = (uint32_t) psgval->bCount;
01230 size = (uint32_t) psgval->wSize;
01231
01232
01233 if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
01234 CFI_INFO
01235 ("%s: The count of DMA Descriptors should be between 1 and %d\n",
01236 __func__, MAX_DMA_DESCS_PER_EP);
01237 return -DWC_E_INVALID;
01238 }
01239
01240
01241
01242 if (size == 0) {
01243
01244 CFI_INFO("%s: The transfer size should be at least 1 byte\n",
01245 __func__);
01246
01247 return -DWC_E_INVALID;
01248
01249 }
01250
01251 inaddr = psgval->bInEndpointAddress;
01252 outaddr = psgval->bOutEndpointAddress;
01253
01254 epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
01255 epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
01256
01257 if (NULL == epin || NULL == epout) {
01258 CFI_INFO
01259 ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
01260 __func__, inaddr, outaddr);
01261 return -DWC_E_INVALID;
01262 }
01263
01264 epin->ep->dwc_ep.buff_mode = BM_SG;
01265 dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
01266
01267 epout->ep->dwc_ep.buff_mode = BM_SG;
01268 dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
01269
01270 return 0;
01271 }
01272
01276 static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01277 {
01278 cfi_ep_t *ep;
01279 uint8_t addr;
01280 ddma_align_buffer_setup_t *palignval;
01281
01282 palignval = (ddma_align_buffer_setup_t *) buf;
01283 addr = palignval->bEndpointAddress;
01284
01285 ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01286
01287 if (NULL == ep) {
01288 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01289 __func__, addr);
01290 return -DWC_E_INVALID;
01291 }
01292
01293 ep->ep->dwc_ep.buff_mode = BM_ALIGN;
01294 dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
01295
01296 return 0;
01297 }
01298
01302 static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01303 {
01304 uint8_t addr;
01305 cfi_ep_t *ep;
01306 struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
01307 uint16_t *pVals;
01308 uint32_t desccount;
01309 int i;
01310 uint16_t mps;
01311
01312 pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
01313 desccount = (uint32_t) pConcatValHdr->bDescCount;
01314 pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
01315
01316
01317 if (desccount > MAX_DMA_DESCS_PER_EP) {
01318 CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
01319 __func__, MAX_DMA_DESCS_PER_EP);
01320 return -DWC_E_INVALID;
01321 }
01322
01323 addr = pConcatValHdr->bEndpointAddress;
01324 ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01325 if (NULL == ep) {
01326 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01327 __func__, addr);
01328 return -DWC_E_INVALID;
01329 }
01330
01331 mps = UGETW(ep->ep->desc->wMaxPacketSize);
01332
01333 #if 0
01334 for (i = 0; i < desccount; i++) {
01335 CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
01336 }
01337 CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
01338 #endif
01339
01340
01341 for (i = 0; i < desccount; i++) {
01342 if (pVals[i] > mps) {
01343 CFI_INFO
01344 ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
01345 __func__, i, pVals[i]);
01346 return -DWC_E_INVALID;
01347 }
01348 }
01349
01350 ep->ep->dwc_ep.buff_mode = BM_CONCAT;
01351 dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
01352
01353
01354 if (ep->bm_concat->wTxBytes) {
01355 DWC_FREE(ep->bm_concat->wTxBytes);
01356 }
01357
01358
01359 ep->bm_concat->wTxBytes =
01360 DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
01361 if (NULL == ep->bm_concat->wTxBytes) {
01362 CFI_INFO("%s: Unable to allocate memory\n", __func__);
01363 return -DWC_E_NO_MEMORY;
01364 }
01365
01366
01367 dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
01368 sizeof(uint16_t) * pConcatValHdr->bDescCount);
01369
01370 return 0;
01371 }
01372
01381 static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
01382 {
01383 dwc_otg_core_params_t *params = core_if->core_params;
01384 uint16_t dfifo_total = 0;
01385 int i;
01386
01387
01388 dfifo_total =
01389 params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
01390
01391
01392 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01393 dfifo_total += params->dev_tx_fifo_size[i];
01394 }
01395
01396 return dfifo_total;
01397 }
01398
01407 static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
01408 {
01409 switch (wValue >> 8) {
01410 case 0:
01411 return (core_if->pwron_rxfsiz <
01412 32768) ? core_if->pwron_rxfsiz : 32768;
01413 break;
01414 case 1:
01415 return core_if->core_params->dev_rx_fifo_size;
01416 break;
01417 default:
01418 return -DWC_E_INVALID;
01419 break;
01420 }
01421 }
01422
01431 static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
01432 {
01433 dwc_otg_pcd_ep_t *ep;
01434
01435 ep = get_ep_by_addr(pcd, wValue & 0xff);
01436
01437 if (NULL == ep) {
01438 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01439 __func__, wValue & 0xff);
01440 return -DWC_E_INVALID;
01441 }
01442
01443 if (!ep->dwc_ep.is_in) {
01444 CFI_INFO
01445 ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
01446 __func__, wValue & 0xff);
01447 return -DWC_E_INVALID;
01448 }
01449
01450 switch (wValue >> 8) {
01451 case 0:
01452 return (GET_CORE_IF(pcd)->pwron_txfsiz
01453 [ep->dwc_ep.tx_fifo_num - 1] <
01454 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
01455 dwc_ep.tx_fifo_num
01456 - 1] : 32768;
01457 break;
01458 case 1:
01459 return GET_CORE_IF(pcd)->core_params->
01460 dev_tx_fifo_size[ep->dwc_ep.num - 1];
01461 break;
01462 default:
01463 return -DWC_E_INVALID;
01464 break;
01465 }
01466 }
01467
01477 static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
01478 {
01479 uint16_t dfifo_actual = 0;
01480 dwc_otg_core_params_t *params = core_if->core_params;
01481 uint16_t start_addr = 0;
01482 int i;
01483
01484 dfifo_actual =
01485 params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
01486
01487 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01488 dfifo_actual += params->dev_tx_fifo_size[i];
01489 }
01490
01491 if (dfifo_actual > core_if->total_fifo_size) {
01492 return 0;
01493 }
01494
01495 if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
01496 return 0;
01497
01498 if (params->dev_nperio_tx_fifo_size > 32768
01499 || params->dev_nperio_tx_fifo_size < 16)
01500 return 0;
01501
01502 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01503
01504 if (params->dev_tx_fifo_size[i] > 768
01505 || params->dev_tx_fifo_size[i] < 4)
01506 return 0;
01507 }
01508
01509 if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
01510 return 0;
01511 start_addr = params->dev_rx_fifo_size;
01512
01513 if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
01514 return 0;
01515 start_addr += params->dev_nperio_tx_fifo_size;
01516
01517 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01518
01519 if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
01520 return 0;
01521 start_addr += params->dev_tx_fifo_size[i];
01522 }
01523
01524 return 1;
01525 }
01526
01535 static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
01536 {
01537 int i = 0;
01538 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
01539 dwc_otg_core_params_t *params = core_if->core_params;
01540 uint32_t rx_fifo_size;
01541 fifosize_data_t nptxfifosize;
01542 fifosize_data_t txfifosize[15];
01543
01544 uint32_t rx_fsz_bak;
01545 uint32_t nptxfsz_bak;
01546 uint32_t txfsz_bak[15];
01547
01548 uint16_t start_address;
01549 uint8_t retval = 1;
01550
01551 if (!check_fifo_sizes(core_if)) {
01552 return 0;
01553 }
01554
01555
01556 if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
01557 rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
01558 rx_fifo_size = params->dev_rx_fifo_size;
01559 DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569 nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
01570 nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
01571 start_address = params->dev_rx_fifo_size;
01572 nptxfifosize.b.startaddr = start_address;
01573
01574 DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
01575
01576 start_address += nptxfifosize.b.depth;
01577
01578 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01579 txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
01580
01581 txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
01582 txfifosize[i].b.startaddr = start_address;
01583 DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
01584 txfifosize[i].d32);
01585
01586 start_address += txfifosize[i].b.depth;
01587 }
01588
01590 if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
01591 retval = 0;
01592 }
01593
01594 if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
01595 retval = 0;
01596 }
01597
01598 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01599 if (txfifosize[i].d32 !=
01600 DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
01601 retval = 0;
01602 }
01603 }
01604
01606 if (retval == 0) {
01607 DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
01608
01609
01610 DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
01611
01612 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01613 DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
01614 txfsz_bak[i]);
01615 }
01616 }
01617 } else {
01618 return 0;
01619 }
01620
01621
01622 dwc_otg_flush_tx_fifo(core_if, 0x10);
01623 dwc_otg_flush_rx_fifo(core_if);
01624
01625 return retval;
01626 }
01627
01631 static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
01632 {
01633 int retval;
01634 uint32_t fsiz;
01635 uint16_t size;
01636 uint16_t ep_addr;
01637 dwc_otg_pcd_ep_t *ep;
01638 dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
01639 tx_fifo_size_setup_t *ptxfifoval;
01640
01641 ptxfifoval = (tx_fifo_size_setup_t *) buf;
01642 ep_addr = ptxfifoval->bEndpointAddress;
01643 size = ptxfifoval->wDepth;
01644
01645 ep = get_ep_by_addr(pcd, ep_addr);
01646
01647 CFI_INFO
01648 ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
01649 __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
01650
01651 if (NULL == ep) {
01652 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01653 __func__, ep_addr);
01654 return -DWC_E_INVALID;
01655 }
01656
01657 fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
01658 params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
01659
01660 if (resize_fifos(GET_CORE_IF(pcd))) {
01661 retval = 0;
01662 } else {
01663 CFI_INFO
01664 ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
01665 __func__, ep_addr);
01666 params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
01667 retval = -DWC_E_INVALID;
01668 }
01669
01670 return retval;
01671 }
01672
01676 static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
01677 {
01678 int retval;
01679 uint32_t fsiz;
01680 uint16_t size;
01681 dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
01682 rx_fifo_size_setup_t *prxfifoval;
01683
01684 prxfifoval = (rx_fifo_size_setup_t *) buf;
01685 size = prxfifoval->wDepth;
01686
01687 fsiz = params->dev_rx_fifo_size;
01688 params->dev_rx_fifo_size = size;
01689
01690 if (resize_fifos(GET_CORE_IF(pcd))) {
01691 retval = 0;
01692 } else {
01693 CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
01694 __func__);
01695 params->dev_rx_fifo_size = fsiz;
01696 retval = -DWC_E_INVALID;
01697 }
01698
01699 return retval;
01700 }
01701
01705 static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
01706 struct cfi_usb_ctrlrequest *req)
01707 {
01708 int retval = -DWC_E_INVALID;
01709 uint8_t addr;
01710 cfi_ep_t *ep;
01711
01712
01713 addr = req->wValue & 0xFF;
01714 if (addr == 0)
01715 return retval;
01716
01717 ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01718 if (NULL == ep) {
01719 CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
01720 __func__, addr);
01721 return retval;
01722 }
01723
01724 dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
01725 retval = BS_SG_VAL_DESC_LEN;
01726 return retval;
01727 }
01728
01733 static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
01734 struct cfi_usb_ctrlrequest *req)
01735 {
01736 int retval = -DWC_E_INVALID;
01737 uint8_t addr;
01738 cfi_ep_t *ep;
01739 uint8_t desc_count;
01740
01741
01742 addr = req->wValue & 0xFF;
01743 if (addr == 0)
01744 return retval;
01745
01746 ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01747 if (NULL == ep) {
01748 CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
01749 __func__, addr);
01750 return retval;
01751 }
01752
01753
01754 dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
01755
01756 buf += BS_CONCAT_VAL_HDR_LEN;
01757
01758 desc_count = ep->bm_concat->hdr.bDescCount;
01759
01760 dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
01761
01762 retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
01763 return retval;
01764 }
01765
01772 static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
01773 struct cfi_usb_ctrlrequest *req)
01774 {
01775 int retval = -DWC_E_INVALID;
01776 uint8_t addr;
01777 cfi_ep_t *ep;
01778
01779
01780 addr = req->wValue & 0xFF;
01781 if (addr == 0)
01782 return retval;
01783
01784 ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01785 if (NULL == ep) {
01786 CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
01787 __func__, addr);
01788 return retval;
01789 }
01790
01791 dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
01792 retval = BS_ALIGN_VAL_HDR_LEN;
01793
01794 return retval;
01795 }
01796
01804 static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
01805 {
01806 int retval = -DWC_E_NOT_SUPPORTED;
01807 uint16_t wIndex, wValue;
01808 uint8_t bRequest;
01809 struct dwc_otg_core_if *coreif;
01810 cfiobject_t *cfi = pcd->cfi;
01811 struct cfi_usb_ctrlrequest *ctrl_req;
01812 uint8_t *buf;
01813 ctrl_req = &cfi->ctrl_req;
01814
01815 buf = pcd->cfi->ctrl_req.data;
01816
01817 coreif = GET_CORE_IF(pcd);
01818 bRequest = ctrl_req->bRequest;
01819 wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
01820 wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
01821
01822
01823 switch (wIndex) {
01824 case FT_ID_DMA_BUFFER_SETUP:
01825
01826 if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
01827 return retval;
01828
01829
01830 cfi->need_gadget_att = 1;
01831 break;
01832
01833 case FT_ID_DMA_BUFF_ALIGN:
01834 if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
01835 return retval;
01836 cfi->need_gadget_att = 1;
01837 break;
01838
01839 case FT_ID_DMA_CONCAT_SETUP:
01840
01841 if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
01842 return retval;
01843 cfi->need_gadget_att = 1;
01844 break;
01845
01846 case FT_ID_DMA_CIRCULAR:
01847 CFI_INFO("FT_ID_DMA_CIRCULAR\n");
01848 break;
01849
01850 case FT_ID_THRESHOLD_SETUP:
01851 CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
01852 break;
01853
01854 case FT_ID_DFIFO_DEPTH:
01855 CFI_INFO("FT_ID_DFIFO_DEPTH\n");
01856 break;
01857
01858 case FT_ID_TX_FIFO_DEPTH:
01859 CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
01860 if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
01861 return retval;
01862 cfi->need_gadget_att = 0;
01863 break;
01864
01865 case FT_ID_RX_FIFO_DEPTH:
01866 CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
01867 if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
01868 return retval;
01869 cfi->need_gadget_att = 0;
01870 break;
01871 }
01872
01873 return retval;
01874 }
01875
01876 #endif //DWC_UTE_CFI