static void monitor_setup_transfer(unsigned long para) { dwc_otg_pcd_t *pcd; int in_ep_ctrl=0; int in_ep_tsiz=0; dwc_otg_core_if_t *core_if; dwc_otg_dev_if_t *dev_if; pcd = (dwc_otg_pcd_t *)para; if(pcd==NULL) return; core_if = GET_CORE_IF(pcd); dev_if = core_if->dev_if; if(pcd->ep0state == EP0_DISCONNECT) return; in_ep_ctrl = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); in_ep_tsiz = dwc_read_reg32(&dev_if->in_ep_regs[0]->dieptsiz); if((in_ep_ctrl & 0x80000000) && (in_ep_tsiz & 0x80000)) suspend_count++; else suspend_count=0; if(suspend_count > 5){ void dwc_udc_startup(void); void dwc_udc_shutdown(void); pr_info("Reset USB Controller..."); dwc_udc_shutdown(); mdelay(500); dwc_udc_startup(); } }
/** * This function completes the request for the 'BULK' EP. If there are * additional requests for the EP in the queue they will be started. */ static void complete_ep( int ep_num,int is_in ) { deptsiz_data_t deptsiz; pcd_struct_t *pcd = &this_pcd[ep_num]; dwc_ep_t *ep = &g_dwc_eps[ep_num]; if (is_in) { pcd->xfer_len = ep->xfer_count;//////////////// deptsiz.d32 = dwc_read_reg32(DWC_REG_IN_EP_TSIZE(ep_num)); if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0 && ep->xfer_count == ep->xfer_len) { ep->start_xfer_buff = 0; ep->xfer_buff = 0; ep->xfer_len = 0; } } else {/* OUT Transfer */ deptsiz.d32 = dwc_read_reg32(DWC_REG_OUT_EP_TSIZE(ep_num)); pcd->xfer_len = ep->xfer_count; ep->start_xfer_buff = 0; ep->xfer_buff = 0; ep->xfer_len = 0; } do_bulk_complete(pcd); }
/** * This function reads a packet from the Rx FIFO into the destination * buffer. To read SETUP data use dwc_otg_read_setup_packet. * * @param _dest Destination buffer for the packet. * @param _bytes Number of bytes to copy to the destination. */ static void dwc_otg_read_packet(uint8_t *_dest, uint16_t _bytes) //Elvis Fool, add 'static' { int i; uint32_t buffer =0; uint8_t* pbyte = _dest; /** * @todo Account for the case where _dest is not dword aligned. This * requires reading data from the FIFO into a uint32_t temp buffer, * then moving it into the data buffer. */ //DBG("dwc_otg_read_packet() dest: %p, len: %d\n",_dest,_bytes); if(((unsigned int)_dest &0x3) == 0) for(i=0; i<_bytes; i+=4){ *(uint32_t*)_dest = dwc_read_reg32(DWC_REG_DATA_FIFO_START); _dest+=4; } else for (i=0; i<_bytes; i++) { if((i % 4) ==0) buffer =dwc_read_reg32(DWC_REG_DATA_FIFO_START); *(uint8_t*)pbyte ++ = buffer; buffer >>= 8; } return; }
/** * This function reads a setup packet from the Rx FIFO into the destination * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) * Interrupt routine when a SETUP packet has been received in Slave mode. * * @param _core_if Programming view of DWC_otg controller. * @param _dest Destination buffer for packet data. */ void dwc_otg_read_setup_packet(uint32_t *_dest) { /* Get the 8 bytes of a setup transaction data */ DBG("dwc_otg_read_setup_packet()\n"); /* Pop 2 DWORDS off the receive data FIFO into memory */ _dest[0] = dwc_read_reg32(DWC_REG_DATA_FIFO_START); _dest[1] = dwc_read_reg32(DWC_REG_DATA_FIFO_START); }
/** * Show the Bus Suspend status */ static ssize_t bussuspend_show( struct device *_dev, struct device_attribute *attr, char *buf) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); hprt0_data_t val; val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0); return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp); }
/** * Show the value of the register at the offset in the reg_offset * attribute. */ static ssize_t regvalue_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); #else dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); #endif uint32_t val; volatile uint32_t *addr; if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { /* Calculate the address */ addr = (uint32_t*)(otg_dev->reg_offset + (uint8_t*)otg_dev->base); //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr); val = dwc_read_reg32( addr ); return snprintf(buf, sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n")+1, "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset, val); } else { dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset); return sprintf(buf, "invalid offset\n" ); } }
/* pullup the data line(D+ for high/full speed) */ static ssize_t pullup_show(struct device *_dev, struct device_attribute *attr, char *buf) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); dctl_data_t val; val.d32 = dwc_read_reg32(&otg_dev->core_if->dev_if->dev_global_regs->dctl); return sprintf(buf, "%s\n", val.b.sftdiscon ? "off":"on"); }
/** * Set the Bus Suspend status */ static ssize_t bussuspend_store(struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); uint32_t in; uint32_t *addr; hprt0_data_t mem; if(strncmp(buf, "1", sizeof("1")-1) == 0) in = 1; else if(strncmp(buf, "0", sizeof("0")-1) == 0) in = 0; else in = simple_strtoul(buf, NULL, 16); addr = (uint32_t *) otg_dev->core_if->host_if->hprt0; mem.d32 = dwc_read_reg32(addr); mem.b.prtsusp = in; dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t) addr, mem.d32); dwc_write_reg32(addr, mem.d32); return count; }
/** * Set the Bus Power status */ static ssize_t buspower_store( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif const char *buf, size_t count ) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); #else dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); #endif uint32_t on = simple_strtoul(buf, NULL, 16); uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0; hprt0_data_t mem; mem.d32 = dwc_read_reg32(addr); mem.b.prtpwr = on; //dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32); dwc_write_reg32(addr, mem.d32); return count; }
/** * Displays the time required to write the GNPTXFSIZ register many times (the * output shows the number of times the register is written). */ static ssize_t wr_reg_test_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); #else dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); #endif uint32_t reg_val; int i; int time; int start_jiffies; printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", HZ, MSEC_PER_JIFFIE, loops_per_jiffy); reg_val = dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz); start_jiffies = jiffies; for (i = 0; i < RW_REG_COUNT; i++) { dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz, reg_val); } time = jiffies - start_jiffies; return sprintf( buf, "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); }
/** * Show the HNP status bit */ static ssize_t hnp_show( struct device *_dev, struct device_attribute *attr, char *buf) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); gotgctl_data_t val; val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl)); return sprintf (buf, "HstNegScs = 0x%x\n", val.b.hstnegscs); }
/** * Show the Bus Power status */ static ssize_t buspower_show( struct device *_dev, struct device_attribute *attr, char *buf) { dwc_otg_device_t *otg_dev = _dev->platform_data; hprt0_data_t val; val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0); return sprintf (buf, "Bus Power = 0x%x\n", val.b.prtpwr); }
int dwc_pcd_irq() { gintsts_data_t gintr_status; gintsts_data_t gintr_msk; gintr_msk.d32 = dwc_read_reg32(DWC_REG_GINTMSK); gintr_status.d32 = dwc_read_reg32(DWC_REG_GINTSTS); if((gintr_status.d32 & gintr_msk.d32)== 0) return 0; //DBG("irq gintmsk: 0x%08x\n",gintr_msk.d32); //DBG("irq gintrsts: 0x%08x\n",gintr_status.d32); gintr_status.d32 = gintr_status.d32 & gintr_msk.d32; //DBG("irq gintmsk & gintrsts = 0x%08x\n",gintr_status.d32); if (gintr_status.b.rxstsqlvl) { dwc_otg_pcd_handle_rx_status_q_level_intr(); } if (gintr_status.b.nptxfempty) { dwc_otg_pcd_handle_np_tx_fifo_empty_intr( ); } if (gintr_status.b.usbreset) { dwc_otg_pcd_handle_usb_reset_intr( ); } if (gintr_status.b.enumdone) { dwc_otg_pcd_handle_enum_done_intr(); } if (gintr_status.b.epmismatch) { //dwc_otg_pcd_handle_ep_mismatch_intr( core_if ); } if (gintr_status.b.inepint) { dwc_otg_pcd_handle_in_ep_intr(); } if (gintr_status.b.outepintr) { dwc_otg_pcd_handle_out_ep_intr( ); } dwc_write_reg32(DWC_REG_GINTSTS,gintr_status.d32); flush_cpu_cache(); return 0; }
/** * Show the SRP status bit */ static ssize_t srp_show( struct device *_dev, struct device_attribute *attr, char *buf) { #ifndef DWC_HOST_ONLY dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); gotgctl_data_t val; val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl)); return sprintf (buf, "SesReqScs = 0x%x\n", val.b.sesreqscs); #else return sprintf(buf, "Host Only Mode!\n"); #endif }
/** * Show the Bus Suspend status */ static ssize_t bussuspend_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); hprt0_data_t val; val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0); return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp); }
/** * Show the status of Remote Wakeup. */ static ssize_t remote_wakeup_show( struct device *_dev, struct device_attribute *attr, char *buf) { #ifndef DWC_HOST_ONLY dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); dctl_data_t val; val.d32 = dwc_read_reg32( &otg_dev->core_if->dev_if->dev_global_regs->dctl); return sprintf( buf, "Remote Wakeup = %d Enabled = %d\n", val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable); #else return sprintf(buf, "Host Only Mode!\n"); #endif }
/** * Show the HNP status bit */ static ssize_t hnp_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); gotgctl_data_t val; val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl)); return sprintf (buf, "HstNegScs = 0x%x\n", val.b.hstnegscs); }
/** * Set the HNP Request bit */ static ssize_t hnp_store( struct device *_dev, struct device_attribute *attr, const char *buf, size_t count ) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); uint32_t in = simple_strtoul(buf, NULL, 16); uint32_t *addr = (uint32_t *)&(otg_dev->core_if->core_global_regs->gotgctl); gotgctl_data_t mem; mem.d32 = dwc_read_reg32(addr); mem.b.hnpreq = in; dev_dbg(_dev, "Storing Address=%p Data=0x%08x\n", addr, mem.d32); dwc_write_reg32(addr, mem.d32); return count; }
/** * Set the Bus Suspend status */ static ssize_t bussuspend_store( struct device *_dev, struct device_attribute *attr, const char *buf, size_t count ) { dwc_otg_device_t *otg_dev = _dev->platform_data; uint32_t in = simple_strtoul(buf, NULL, 16); uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0; hprt0_data_t mem; mem.d32 = dwc_read_reg32(addr); mem.b.prtsusp = in; dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32); dwc_write_reg32(addr, mem.d32); return count; }
/** * This function reads a packet from the Rx FIFO into the destination * buffer. To read SETUP data use dwc_otg_read_setup_packet. * * @param _dest Destination buffer for the packet. * @param _bytes Number of bytes to copy to the destination. */ static void dwc_otg_read_packet(uint8_t *_dest, uint16_t _bytes) //Elvis Fool, add 'static' { int i; /*const char* str = (char*)_dest;*/ uint32_t* pu32 = (uint32_t*)_dest; const unsigned lenIn32 = (_bytes>>2); const unsigned rest = (_bytes & 3); /** * @todo Account for the case where _dest is not dword aligned. This * requires reading data from the FIFO into a uint32_t temp buffer, * then moving it into the data buffer. */ //DBG("dwc_otg_read_packet() dest: %p, len: %d\n",_dest,_bytes); for (i = 0; i < lenIn32; ++i) { *pu32++ = dwc_read_reg32(DWC_REG_DATA_FIFO_START); } if (rest) { const unsigned fifoVal = dwc_read_reg32(DWC_REG_DATA_FIFO_START); uint8_t* pBufDst8 = (uint8_t*)pu32; const uint8_t* pBufSrc8 = (const uint8_t*)&fifoVal; for (i = 0; i < rest; ++i) { *pBufDst8++ = *pBufSrc8++; } } /* *if(!strcmp("power", str)) * printf("%d>", _bytes),printf(str),printf("\n"); */ return; }
int dwc_common_irq() { gotgint_data_t gotgint; gotgint.d32 = dwc_read_reg32(DWC_REG_GOTGINT); if(gotgint.d32 == 0) return 0; // if(gotgint.b.sesreqsucstschng) // { // DBG("Session Request Success Status Change\n"); // } dwc_write_reg32(DWC_REG_GOTGINT,gotgint.d32); // clear intr return 0; }
/** * Show the Bus Power status */ static ssize_t buspower_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); #else dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); #endif hprt0_data_t val; val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0); return sprintf (buf, "Bus Power = 0x%x\n", val.b.prtpwr); }
/** * Set the Bus Power status */ static ssize_t buspower_store( struct device *_dev, struct device_attribute *attr, const char *buf, size_t count ) { dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); uint32_t on = simple_strtoul(buf, NULL, 16); uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0; hprt0_data_t mem; mem.d32 = dwc_read_reg32(addr); mem.b.prtpwr = on; //dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32); dwc_write_reg32(addr, mem.d32); return count; }
static ssize_t rd_reg_test_show( struct device *_dev, struct device_attribute *attr, char *buf) { int i; int time; int start_jiffies; dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", HZ, MSEC_PER_JIFFIE, loops_per_jiffy); start_jiffies = jiffies; for (i = 0; i < RW_REG_COUNT; i++) { dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz); } time = jiffies - start_jiffies; return sprintf( buf, "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", RW_REG_COUNT, time * MSEC_PER_JIFFIE, time ); }
int dwc_core_init() { int32_t snpsid; snpsid = dwc_read_reg32(DWC_REG_GSNPSID); if ((snpsid & 0xFFFFF000) != 0x4F542000) { ERR("Bad value for SNPSID: 0x%08x\n", snpsid); return -1; } ERR("dwc core init is ok!\n");// show printf is ok. /* * Disable the global interrupt until all the interrupt * handlers are installed. */ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ahbcfg.b.glblintrmsk = 1; /* Enable interrupts bit */ dwc_modify_reg32(DWC_REG_GAHBCFG, ahbcfg.d32, 0); /* * Initialize the DWC_otg core. */ dwc_otg_core_init(); dwc_modify_reg32(DWC_REG_DCTL,0,2);// Disconnect data line dwc_otg_pcd_init(); dwc_modify_reg32(DWC_REG_DCTL,2,0);// Connect data line /* * Enable the global interrupt after all the interrupt * handlers are installed. */ dwc_otg_enable_global_interrupts(); return 0; } int dwc_otg_irq() { dwc_common_irq(); dwc_pcd_irq(); return 0; }
/** * This function completes the ep0 control transfer. */ static int32_t ep0_complete_request( pcd_struct_t * pcd) { deptsiz0_data_t deptsiz; int is_last = 0; dwc_ep_t* ep = &g_dwc_eps[0]; DBG("ep0_complete_request()\n"); if (pcd->ep0state == EP0_STATUS) { is_last = 1; } else if (ep->xfer_len == 0) { ep->xfer_len = 0; ep->xfer_count = 0; ep->sent_zlp = 1; dwc_otg_ep_start_transfer( ep ); return 1; } else if (ep->is_in) { deptsiz.d32 = dwc_read_reg32(DWC_REG_IN_EP_TSIZE(0) ); if (deptsiz.b.xfersize == 0) { /* Is a Zero Len Packet needed? */ do_setup_out_status_phase(pcd); } } else { /* ep0-OUT */ do_setup_in_status_phase(pcd); } /* Complete the request */ if (is_last) { ep->start_xfer_buff = 0; ep->xfer_buff = 0; ep->xfer_len = 0; return 1; } return 0; }
int dwc_common_irq(void) { int ret = 0; gotgint_data_t gotgint; gotgint.d32 = dwc_read_reg32(DWC_REG_GOTGINT); if (gotgint.d32 == 0) return 0; if (gotgint.b.sesreqsucstschng) { ERR("Session Request Success Status Change\n"); } if (gotgint.b.sesenddet) { ERR("Session End Detected, Line Disconected\n"); cb_4_dis_connect_intr(); } dwc_write_reg32(DWC_REG_GOTGINT,gotgint.d32); // clear intr return ret; }
/** * Show the SRP status bit */ static ssize_t srp_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { #ifndef DWC_HOST_ONLY #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); #else dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); #endif gotgctl_data_t val; val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl)); return sprintf (buf, "SesReqScs = 0x%x\n", val.b.sesreqscs); #else return sprintf(buf, "Host Only Mode!\n"); #endif }
/** * Displays the time required to write the GNPTXFSIZ register many times (the * output shows the number of times the register is written). */ static ssize_t wr_reg_test_show(struct device *_dev, struct device_attribute *attr, char *buf) { int i; int time; int start_jiffies; dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); dwc_otg_core_if_t *core_if = otg_dev->core_if; uint32_t reg_val; reg_val = dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz); start_jiffies = jiffies; for (i = 0; i < RW_REG_COUNT; i++) { dwc_write_reg32(&core_if->core_global_regs->gnptxfsiz, reg_val); } time = jiffies - start_jiffies; return sprintf(buf, "Time to write GNPTXFSIZ reg %d " "times: %d msecs (%d jiffies)\n", RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); }
/** * Show the status of Remote Wakeup. */ static ssize_t remote_wakeup_show( struct device *_dev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct device_attribute *attr, #endif char *buf) { #ifndef DWC_HOST_ONLY #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); #else dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); #endif dctl_data_t val; val.d32 = dwc_read_reg32( &otg_dev->core_if->dev_if->dev_global_regs->dctl); return sprintf( buf, "Remote Wakeup = %d Enabled = %d\n", val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable); #else return sprintf(buf, "Host Only Mode!\n"); #endif }