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