void request_done_tasklet(unsigned long data) { ifxpcd_ep_t *_ifxep = (ifxpcd_ep_t *)data; ifxpcd_request_t *req; unsigned long flags=0; int k=10; _ifxep->cmpt_tasklet_in_process=1; while (k) { SPIN_LOCK_IRQSAVE(&_ifxep->cmp_lock,flags); if(_ifxep->queue_cmpt.next != &_ifxep->queue_cmpt) { req = list_entry(_ifxep->queue_cmpt.next, ifxpcd_request_t,trq); list_del_init(&req->trq); SPIN_UNLOCK_IRQRESTORE(&_ifxep->cmp_lock,flags); if(req->sysreq.complete) req->sysreq.complete(&_ifxep->sysep, &req->sysreq); else { #ifdef __req_num_dbg__ IFX_ERROR("%s() no complete EP%d Req%d\n",__func__,_ifxep->num, req->reqid); #else IFX_ERROR("%s() no complete EP%d Req %p\n",__func__,_ifxep->num, req); #endif } } else { SPIN_UNLOCK_IRQRESTORE(&_ifxep->cmp_lock,flags); break; } k--; } if(!list_empty(&_ifxep->queue_cmpt)) { #ifdef __GADGET_TASKLET_HIGH__ tasklet_hi_schedule(&_ifxep->cmpt_tasklet); #else tasklet_schedule(&_ifxep->cmpt_tasklet); #endif } else _ifxep->cmpt_tasklet_in_process=0; }
int __init ifxusb_driver_init(void) { int retval = 0; IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); IFX_PRINT("%s: version %s\n", ifxusb_driver_name, IFXUSB_VERSION); retval = ifxusb_driver_probe(); if (retval < 0) { IFX_ERROR("%s retval=%d\n", __func__, retval); return retval; } return retval; }
/*! \brief inlined by ifxusb_driver_probe(), handling device mode probing. */ static inline int ifxusb_driver_probe_d(ifxpcd_pcd_t *_pcd, int _irq, uint32_t _iobase, uint32_t _fifomem, uint32_t _fifodbg ) { int retval = 0; IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); #ifdef __DEV_NEW__ ifxusb_power_off (&_pcd->core_if); ifxusb_phy_power_off (&_pcd->core_if); // Test mdelay(500); #endif // __DEV_NEW__ ifxusb_power_on (&_pcd->core_if); mdelay(50); ifxusb_phy_power_on (&_pcd->core_if); // Test mdelay(50); ifxusb_hard_reset(&_pcd->core_if); retval =ifxusb_core_if_init(&_pcd->core_if, _irq, _iobase, _fifomem, _fifodbg); if(retval) return retval; IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); ifxusb_dev_core_init(&_pcd->core_if,&ifxusb_module_params); IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); ifxusb_disable_global_interrupts( &_pcd->core_if); /* The driver is now initialized and need to be registered into Linux USB Gadget sub-system */ retval = ifxpcd_init(); IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); if (retval != 0) { IFX_ERROR("_pcd_init failed\n"); return retval; } //ifxusb_enable_global_interrupts( _pcd->core_if ); // this should be done at gadget bind or start return 0; }
/*! \brief inlined by ifxusb_driver_probe(), handling host mode probing. Run at each host core. */ static inline int ifxusb_driver_probe_h(ifxhcd_hcd_t *_hcd, int _irq, uint32_t _iobase, uint32_t _fifomem, uint32_t _fifodbg ) { int retval = 0; IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); ifxusb_power_on_h (&_hcd->core_if); mdelay(50); ifxusb_phy_power_on_h (&_hcd->core_if); // Test mdelay(50); ifxusb_hard_reset_h(&_hcd->core_if); retval =ifxusb_core_if_init_h(&_hcd->core_if, _irq, _iobase, _fifomem, _fifodbg); if(retval) return retval; ifxusb_host_core_init(&_hcd->core_if,&ifxusb_module_params_h); ifxusb_disable_global_interrupts_h( &_hcd->core_if); /* The driver is now initialized and need to be registered into Linux USB sub-system */ retval = ifxhcd_init(_hcd); // hook the hcd into usb ss if (retval != 0) { IFX_ERROR("_hcd_init failed\n"); return retval; } //ifxusb_enable_global_interrupts_h( _hcd->core_if ); // this should be done at hcd_start , including hcd_interrupt return 0; }
/*! \brief This function completes a request. It call's the request call back. */ static void request_done_ep0(ifxpcd_request_t *_ifxreq, int _status) { IFX_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__,_ifxreq); if(!_ifxreq) { IFX_ERROR("%s() %d invalid _ifxreq\n",__func__,__LINE__); return; } _ifxreq->sysreq.status = _status; list_del_init(&_ifxreq->trq); #ifdef __DO_PCD_UNLOCK__ SPIN_UNLOCK(&ifxusb_pcd.lock); #endif if(_ifxreq->sysreq.complete) _ifxreq->sysreq.complete(&ifxusb_pcd.ifxep[0].sysep, &_ifxreq->sysreq); #ifdef __DO_PCD_UNLOCK__ SPIN_LOCK(&ifxusb_pcd.lock); #endif }
int __init ifxusb_pcd_driver_init(void) #endif { int retval = 0; IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ ); #if defined(__IS_HOST__) IFX_PRINT("%s: version %s\n", ifxusb_hcd_driver_name, IFXUSB_VERSION); #else IFX_PRINT("%s: version %s\n", ifxusb_pcd_driver_name, IFXUSB_VERSION); #endif #if 0 #if defined(__IS_TWINPASS__) IFX_PRINT(" OPTION: __IS_TWINPASS__\n"); #elif defined(__IS_DANUBE__) IFX_PRINT(" OPTION: __IS_DANUBE__\n"); #elif defined(__IS_AMAZON_SE__) IFX_PRINT(" OPTION: __IS_AMAZON_SE__\n"); #elif defined(__IS_AR9__) IFX_PRINT(" OPTION: __IS_AR9__\n"); #elif defined(__IS_VR9__) IFX_PRINT(" OPTION: __IS_VR9__\n"); #elif defined(__IS_AR10__) IFX_PRINT(" OPTION: __IS_AR10__\n"); #else IFX_PRINT(" OPTION: NO PLATFORM DEFINED\n"); #endif #ifdef __UEIP__ IFX_PRINT(" OPTION: __UEIP__\n"); #endif #ifdef __PHY_LONG_PREEMP__ IFX_PRINT(" OPTION: __PHY_LONG_PREEMP__\n"); #endif #ifdef __FORCE_USB11__ IFX_PRINT(" OPTION: __FORCE_USB11__\n"); #endif #ifdef __UNALIGNED_BUF_ADJ__ IFX_PRINT(" OPTION: __UNALIGNED_BUF_ADJ__\n"); #endif #ifdef __UNALIGNED_BUF_CHK__ IFX_PRINT(" OPTION: __UNALIGNED_BUF_CHK__\n"); #endif #ifdef __UNALIGNED_BUF_BURST__ IFX_PRINT(" OPTION: __UNALIGNED_BUF_BURST__\n"); #endif #ifdef __DEBUG__ IFX_PRINT(" OPTION: __DEBUG__\n"); #endif #ifdef __ENABLE_DUMP__ IFX_PRINT(" OPTION: __ENABLE_DUMP__\n"); #endif #ifdef __IS_HOST__ IFX_PRINT(" OPTION: __IS_HOST__\n"); #ifdef __IS_DUAL__ IFX_PRINT(" __IS_DUAL__\n"); #endif #ifdef __IS_FIRST__ IFX_PRINT(" __IS_FIRST__\n"); #endif #ifdef __IS_SECOND__ IFX_PRINT(" __IS_SECOND__\n"); #endif #ifdef __WITH_HS_ELECT_TST__ IFX_PRINT(" __WITH_HS_ELECT_TST__\n"); #endif #ifdef __EN_ISOC__ IFX_PRINT(" __EN_ISOC__\n"); #endif #ifdef __EN_ISOC_SPLIT__ IFX_PRINT(" __EN_ISOC_SPLIT__\n"); #endif #ifdef __EPQD_DESTROY_TIMEOUT__ IFX_PRINT(" __EPQD_DESTROY_TIMEOUT__\n"); #endif #ifdef __DYN_SOF_INTR__ IFX_PRINT(" __DYN_SOF_INTR__\n"); #endif #else IFX_PRINT(" OPTION: __IS_DEVICE__\n"); #ifdef __DED_INTR__ IFX_PRINT(" __DED_INTR__\n"); #endif #ifdef __DED_FIFO__ IFX_PRINT(" __DED_FIFO__\n"); #endif #ifdef __DESC_DMA__ IFX_PRINT(" __DESC_DMA__\n"); #endif #ifdef __IS_FIRST__ IFX_PRINT(" __IS_FIRST__\n"); #endif #ifdef __IS_SECOND__ IFX_PRINT(" __IS_SECOND__\n"); #endif #ifdef __GADGET_TASKLET_TX__ IFX_PRINT(" __GADGET_TASKLET_TX__\n"); #endif #ifdef __GADGET_TASKLET_RX__ IFX_PRINT(" __GADGET_TASKLET_RX__\n"); #endif #ifdef __GADGET_TASKLET_HIGH__ IFX_PRINT(" __GADGET_TASKLET_HIGH__\n"); #endif #ifdef __DO_PCD_UNLOCK__ IFX_PRINT(" __DO_PCD_UNLOCK__\n"); #endif #ifdef __GADGET_LED__ IFX_PRINT(" __GADGET_LED__\n"); #endif #ifdef __ECM_NO_INTR__ IFX_PRINT(" __ECM_NO_INTR__\n"); #endif #ifdef __NOSWAPINCTRL__ IFX_PRINT(" __NOSWAPINCTRL__\n"); #endif #ifdef __MAC_ECM_FIX__ IFX_PRINT(" __MAC_ECM_FIX__\n"); #endif #ifdef __RETAIN_BUF_TX__ IFX_PRINT(" __RETAIN_BUF_TX__\n"); #endif #ifdef __RETAIN_BUF_RX__ IFX_PRINT(" __RETAIN_BUF_RX__\n"); #endif #ifdef __QUICKNAK__ IFX_PRINT(" __QUICKNAK__\n"); #endif #endif #endif retval = platform_driver_register(&ifxusb_driver); if (retval < 0) { IFX_ERROR("%s retval=%d\n", __func__, retval); return retval; } #ifdef __IS_HOST__ ifxusb_device.name = ifxusb_hcd_driver_name; #else ifxusb_device.name = ifxusb_pcd_driver_name; #endif if (ifxusb_device.dev.parent) retval = -EBUSY; else retval = platform_device_register(&ifxusb_device); if (retval < 0) { IFX_ERROR("%s retval=%d\n", __func__, retval); platform_driver_unregister(&ifxusb_driver); return retval; } return retval; }
void request_done(ifxpcd_ep_t *_ifxep, ifxpcd_request_t *_ifxreq, int _status) { IFX_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, _ifxep,_ifxreq); if(!_ifxep) { IFX_ERROR("%s() %d invalid _ifxep\n",__func__,__LINE__); return; } if(!_ifxreq) { IFX_ERROR("%s() %d invalid _ifxreq\n",__func__,__LINE__); return; } if(_ifxep->num==0) { request_done_ep0(_ifxreq, _status); return; } _ifxreq->sysreq.status = _status; if(_ifxep->type==IFXUSB_EP_TYPE_INTR) { list_del_init(&_ifxreq->trq); if(_ifxreq->sysreq.complete) { #ifdef __DO_PCD_UNLOCK__ SPIN_UNLOCK(&ifxusb_pcd.lock); #endif _ifxreq->sysreq.complete(&_ifxep->sysep, &_ifxreq->sysreq); #ifdef __DO_PCD_UNLOCK__ SPIN_LOCK(&ifxusb_pcd.lock); #endif } } else if(_ifxep->is_in) // Tx { #if defined(__GADGET_TASKLET_TX__) list_del_init(&_ifxreq->trq); list_add_tail(&_ifxreq->trq, &_ifxep->queue_cmpt); if(!_ifxreq->sysreq.no_interrupt && !_ifxep->cmpt_tasklet_in_process) { #ifdef __GADGET_TASKLET_HIGH__ tasklet_hi_schedule(&_ifxep->cmpt_tasklet); #else tasklet_schedule(&_ifxep->cmpt_tasklet); #endif } #else list_del_init(&_ifxreq->trq); if(!_ifxreq->sysreq.no_interrupt) { while (!list_empty(&_ifxep->queue_cmpt)) { ifxpcd_request_t *req; req = list_entry(_ifxep->queue_cmpt.next, ifxpcd_request_t,trq); list_del_init(&req->trq); if(req->sysreq.complete) { #ifdef __DO_PCD_UNLOCK__ SPIN_UNLOCK(&ifxusb_pcd.lock); #endif req->sysreq.complete(&_ifxep->sysep, &req->sysreq); #ifdef __DO_PCD_UNLOCK__ SPIN_LOCK(&ifxusb_pcd.lock); #endif } else { #ifdef __req_num_dbg__ IFX_ERROR("%s() no complete EP%d Req%d\n",__func__,_ifxep->num, req->reqid); #else IFX_ERROR("%s() no complete EP%d Req %p\n",__func__,_ifxep->num, req); #endif } } if(_ifxreq->sysreq.complete) { #ifdef __DO_PCD_UNLOCK__ SPIN_UNLOCK(&ifxusb_pcd.lock); #endif _ifxreq->sysreq.complete(&_ifxep->sysep, &_ifxreq->sysreq); #ifdef __DO_PCD_UNLOCK__ SPIN_LOCK(&ifxusb_pcd.lock); #endif } else { #ifdef __req_num_dbg__ IFX_ERROR("%s() no complete EP%d Req%d\n",__func__,_ifxep->num, _ifxreq->reqid); #else IFX_ERROR("%s() no complete EP%d Req %p\n",__func__,_ifxep->num, _ifxreq); #endif } } else list_add_tail(&_ifxreq->trq, &_ifxep->queue_cmpt); #endif } else // Rx { #if defined(__GADGET_TASKLET_RX__) if(list_empty(&_ifxep->queue)) // Rx Empty, Reuse { _ifxreq->sysreq.actual=0; _ifxreq->sysreq.status=0; } else if(!_ifxreq->sysreq.no_interrupt && !_ifxep->cmpt_tasklet_in_process) { _ifxep->cmpt_tasklet_in_process=1; list_move_tail(&_ifxreq->trq, &_ifxep->queue_cmpt); #ifdef __GADGET_TASKLET_HIGH__ tasklet_hi_schedule(&_ifxep->cmpt_tasklet); #else tasklet_schedule(&_ifxep->cmpt_tasklet); #endif } else list_move_tail(&_ifxreq->trq, &_ifxep->queue_cmpt); #else if(!_ifxreq->sysreq.no_interrupt) { ifxpcd_request_t *req2; while (!list_empty(&_ifxep->queue_cmpt)) { req = list_entry(_ifxep->queue_cmpt.next, ifxpcd_request_t,trq); list_del_init(&req->trq); if(req->sysreq.complete) { #ifdef __DO_PCD_UNLOCK__ SPIN_UNLOCK(&ifxusb_pcd.lock); #endif req->sysreq.complete(&_ifxep->sysep, &req->sysreq); #ifdef __DO_PCD_UNLOCK__ SPIN_LOCK(&ifxusb_pcd.lock); #endif } else { #ifdef __req_num_dbg__ IFX_ERROR("%s() no complete EP%d Req%d\n",__func__,_ifxep->num, req->reqid); #else IFX_ERROR("%s() no complete EP%d Req %p\n",__func__,_ifxep->num, req); #endif } } if(list_empty(&_ifxep->queue) // Rx Empty, Reuse { _ifxreq->sysreq.actual=0; _ifxreq->sysreq.status=0; list_add_tail(&_ifxreq->trq, &_ifxep->queue); } else { if(_ifxreq->sysreq.complete) { #ifdef __DO_PCD_UNLOCK__ SPIN_UNLOCK(&ifxusb_pcd.lock); #endif _ifxreq->sysreq.complete(&_ifxep->sysep, &_ifxreq->sysreq); #ifdef __DO_PCD_UNLOCK__ SPIN_LOCK(&ifxusb_pcd.lock); #endif } else { #ifdef __req_num_dbg__ IFX_ERROR("%s() no complete EP%d Req%d\n",__func__,_ifxep->num, req->reqid); #else IFX_ERROR("%s() no complete EP%d Req %p\n",__func__,_ifxep->num, req); #endif } } }
/*! \brief This function is called to initialize the IFXUSB CSR data structures. The register addresses in the device and host structures are initialized from the base address supplied by the caller. The calling function must make the OS calls to get the base address of the IFXUSB controller registers. \param _core_if Pointer of core_if structure \param _irq irq number \param _reg_base_addr Base address of IFXUSB core registers \param _fifo_base_addr Fifo base address \param _fifo_dbg_addr Fifo debug address \return 0: success; */ int ifxusb_core_if_init(ifxusb_core_if_t *_core_if, int _irq, uint32_t _reg_base_addr, uint32_t _fifo_base_addr, uint32_t _fifo_dbg_addr) { int retval = 0; uint32_t *reg_base =NULL; uint32_t *fifo_base =NULL; uint32_t *fifo_dbg =NULL; int i; IFX_DEBUGPL(DBG_CILV, "%s(%p,%d,0x%08X,0x%08X,0x%08X)\n", __func__, _core_if, _irq, _reg_base_addr, _fifo_base_addr, _fifo_dbg_addr); if( _core_if == NULL) { IFX_ERROR("%s() invalid _core_if\n", __func__); retval = -ENOMEM; goto fail; } //memset(_core_if, 0, sizeof(ifxusb_core_if_t)); _core_if->irq=_irq; reg_base =ioremap_nocache(_reg_base_addr , IFXUSB_IOMEM_SIZE ); fifo_base =ioremap_nocache(_fifo_base_addr, IFXUSB_FIFOMEM_SIZE); fifo_dbg =ioremap_nocache(_fifo_dbg_addr , IFXUSB_FIFODBG_SIZE); if( reg_base == NULL || fifo_base == NULL || fifo_dbg == NULL) { IFX_ERROR("%s() usb ioremap() failed\n", __func__); retval = -ENOMEM; goto fail; } _core_if->core_global_regs = (ifxusb_core_global_regs_t *)reg_base; /* * Attempt to ensure this device is really a IFXUSB Controller. * Read and verify the SNPSID register contents. The value should be * 0x45F42XXX */ { int32_t snpsid; snpsid = ifxusb_rreg(&_core_if->core_global_regs->gsnpsid); if ((snpsid & 0xFFFFF000) != 0x4F542000) { IFX_ERROR("%s() snpsid error(0x%08x) failed\n", __func__,snpsid); retval = -EINVAL; goto fail; } _core_if->snpsid=snpsid; } #ifdef __IS_HOST__ _core_if->host_global_regs = (ifxusb_host_global_regs_t *) ((uint32_t)reg_base + IFXUSB_HOST_GLOBAL_REG_OFFSET); _core_if->hprt0 = (uint32_t*)((uint32_t)reg_base + IFXUSB_HOST_PORT_REGS_OFFSET); for (i=0; i<MAX_EPS_CHANNELS; i++) { _core_if->hc_regs[i] = (ifxusb_hc_regs_t *) ((uint32_t)reg_base + IFXUSB_HOST_CHAN_REGS_OFFSET + (i * IFXUSB_CHAN_REGS_OFFSET)); IFX_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", i, &_core_if->hc_regs[i]->hcchar); } #endif //__IS_HOST__ #ifdef __IS_DEVICE__ _core_if->dev_global_regs = (ifxusb_device_global_regs_t *)((uint32_t)reg_base + IFXUSB_DEV_GLOBAL_REG_OFFSET); for (i=0; i<MAX_EPS_CHANNELS; i++) { _core_if->in_ep_regs[i] = (ifxusb_dev_in_ep_regs_t *) ((uint32_t)reg_base + IFXUSB_DEV_IN_EP_REG_OFFSET + (i * IFXUSB_EP_REG_OFFSET)); _core_if->out_ep_regs[i] = (ifxusb_dev_out_ep_regs_t *) ((uint32_t)reg_base + IFXUSB_DEV_OUT_EP_REG_OFFSET + (i * IFXUSB_EP_REG_OFFSET)); IFX_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p/%p %p/0x%08X/0x%08X\n", i, &_core_if->in_ep_regs[i]->diepctl, _core_if->in_ep_regs[i], reg_base,IFXUSB_DEV_IN_EP_REG_OFFSET,(i * IFXUSB_EP_REG_OFFSET) ); IFX_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p/%p %p/0x%08X/0x%08X\n", i, &_core_if->out_ep_regs[i]->doepctl, _core_if->out_ep_regs[i], reg_base,IFXUSB_DEV_OUT_EP_REG_OFFSET,(i * IFXUSB_EP_REG_OFFSET) ); } #endif //__IS_DEVICE__ /* Setting the FIFO and other Address. */ for (i=0; i<MAX_EPS_CHANNELS; i++) { _core_if->data_fifo[i] = fifo_base + (i * IFXUSB_DATA_FIFO_SIZE); IFX_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n", i, (unsigned)_core_if->data_fifo[i]); } _core_if->data_fifo_dbg = fifo_dbg; _core_if->pcgcctl = (uint32_t*)(((uint32_t)reg_base) + IFXUSB_PCGCCTL_OFFSET); /* * Store the contents of the hardware configuration registers here for * easy access later. */ _core_if->hwcfg1.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg1); _core_if->hwcfg2.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg2); _core_if->hwcfg3.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg3); _core_if->hwcfg4.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg4); IFX_DEBUGPL(DBG_CILV,"hwcfg1=%08x\n",_core_if->hwcfg1.d32); IFX_DEBUGPL(DBG_CILV,"hwcfg2=%08x\n",_core_if->hwcfg2.d32); IFX_DEBUGPL(DBG_CILV,"hwcfg3=%08x\n",_core_if->hwcfg3.d32); IFX_DEBUGPL(DBG_CILV,"hwcfg4=%08x\n",_core_if->hwcfg4.d32); #ifdef __DED_FIFO__ IFX_PRINT("Waiting for PHY Clock Lock!\n"); while(!( ifxusb_rreg(&_core_if->core_global_regs->grxfsiz) & (1<<9))) { } IFX_PRINT("PHY Clock Locked!\n"); //ifxusb_clean_spram(_core_if,128*1024/4); #endif /* Create new workqueue and init works */ #if 0 _core_if->wq_usb = create_singlethread_workqueue(_core_if->core_name); if(_core_if->wq_usb == 0) { IFX_DEBUGPL(DBG_CIL, "Creation of wq_usb failed\n"); retval = -EINVAL; goto fail; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&core_if->w_conn_id, w_conn_id_status_change, core_if); INIT_WORK(&core_if->w_wkp, w_wakeup_detected, core_if); #else INIT_WORK(&core_if->w_conn_id, w_conn_id_status_change); INIT_DELAYED_WORK(&core_if->w_wkp, w_wakeup_detected); #endif #endif return 0; fail: if( reg_base != NULL) iounmap(reg_base ); if( fifo_base != NULL) iounmap(fifo_base); if( fifo_dbg != NULL) iounmap(fifo_dbg ); return retval; }