static inline void s3c_ep0_complete_out(void) { u32 ep_ctrl; DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n", __func__, readl(®->out_endp[EP0_CON].doepctl)); debug_cond(DEBUG_IN_EP, "%s : Prepare Complete Out packet.\n", __func__); invalidate_dcache_range((unsigned long) usb_ctrl_dma_addr, (unsigned long) usb_ctrl_dma_addr + DMA_BUFFER_SIZE); writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), ®->out_endp[EP0_CON].doeptsiz); writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, ®->out_endp[EP0_CON].doepctl); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n", __func__, readl(®->out_endp[EP0_CON].doepctl)); }
static inline void s3c_ep0_complete_out(void) { u32 ep_ctrl; DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n", __func__, readl(®->out_endp[EP0_CON].doepctl)); DEBUG_IN_EP("%s : Prepare Complete Out packet.\n", __func__); writel((1 << 19) | sizeof(struct usb_ctrlrequest), ®->out_endp[EP0_CON].doeptsiz); writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, ®->out_endp[EP0_CON].doepctl); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n", __func__, readl(®->out_endp[EP0_CON].doepctl)); }
static inline void s3c_udc_pre_setup(void) { u32 ep_ctrl; DEBUG_IN_EP("%s : Prepare Setup packets.\n", __func__); writel((1 << 19) | sizeof(struct usb_ctrlrequest), ®->out_endp[EP0_CON].doeptsiz); writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); writel(ep_ctrl|DEPCTL_EPENA, ®->out_endp[EP0_CON].doepctl); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n", __func__, readl(®->out_endp[EP0_CON].doepctl)); }
static inline void s3c_udc_ep0_zlp(void) { u32 ep_ctrl; writel(virt_to_phys(&usb_ctrl), S3C_UDC_OTG_DIEPDMA(EP0_CON)); writel((1<<19 | 0<<0), S3C_UDC_OTG_DIEPTSIZ(EP0_CON)); ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON)); writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, S3C_UDC_OTG_DIEPCTL(EP0_CON)); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(S3C_UDC_OTG_DIEPCTL(EP0_CON))); }
static inline void s3c_udc_ep0_zlp(struct s3c_udc *dev) { u32 ep_ctrl; __raw_writel(dev->usb_ctrl_dma, dev->regs + S3C_UDC_OTG_DIEPDMA(EP0_CON)); __raw_writel((1<<19 | 0<<0), dev->regs + S3C_UDC_OTG_DIEPTSIZ(EP0_CON)); ep_ctrl = __raw_readl(dev->regs + S3C_UDC_OTG_DIEPCTL(EP0_CON)); __raw_writel(ep_ctrl | DEPCTL_EPENA | DEPCTL_CNAK, dev->regs + S3C_UDC_OTG_DIEPCTL(EP0_CON)); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, __raw_readl(dev->regs + S3C_UDC_OTG_DIEPCTL(EP0_CON))); }
static inline void s3c_udc_ep0_zlp(void) { u32 ep_ctrl; writel(virt_to_phys(&usb_ctrl), S3C_UDC_OTG_DIEPDMA(EP0_CON)); writel((1<<19| 0<<0), S3C_UDC_OTG_DIEPTSIZ(EP0_CON)); ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON)); writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, S3C_UDC_OTG_DIEPCTL(EP0_CON)); if (currentusbstatus == USBSTATUS_VTP) printk("TETHERING::s3c_udc_ep0_zlp\n"); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(S3C_UDC_OTG_DIEPCTL(EP0_CON))); }
static inline void s3c_udc_ep0_zlp(struct s3c_udc *dev) { u32 ep_ctrl; writel(usb_ctrl_dma_addr, ®->in_endp[EP0_CON].diepdma); // writel((1<<19 | 0<<0), ®->in_endp[EP0_CON].dieptsiz); writel((1<<19 ), ®->in_endp[EP0_CON].dieptsiz); ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, ®->in_endp[EP0_CON].diepctl); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); dev->ep0state = WAIT_FOR_IN_COMPLETE; }
/** Write request to FIFO (max write == maxp size) * Return: 0 = still running, 1 = completed, negative = errno */ static int write_fifo(struct elfin_ep *ep, struct elfin_request *req) { u32 max; unsigned count; int is_last, is_short; max = le16_to_cpu(ep->desc->wMaxPacketSize); count = write_packet(ep, req, max); /* last packet is usually short (or a zlp) */ if (unlikely(count != max)) is_last = is_short = 1; else { if (likely(req->req.length != req->req.actual) || req->req.zero) is_last = 0; else is_last = 1; /* interrupt/iso maxpacket may not fill the fifo */ is_short = unlikely(max < ep_maxpacket(ep)); } /* requests complete when all IN data is in the FIFO */ if (is_last) { if(!ep_index(ep)){ // EP0 must not come here BUG(); //usb_set(S3C2410_UDC_EP0_CSR_IPKRDY | S3C2410_UDC_EP0_CSR_DE, // S3C2410_UDC_EP0_CSR_REG, 0); }else{ usb_set(S3C2410_UDC_ICSR1_PKTRDY, ep->csr1, ep_index(ep)); } done(ep, req, 0); return 1; } else{ usb_set(S3C2410_UDC_ICSR1_PKTRDY, ep->csr1, ep_index(ep)); } DEBUG_EP0("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__, ep->ep.name, count, is_last ? "/L" : "", is_short ? "/S" : "", req->req.length - req->req.actual, req); return 0; }
static inline void s3c_udc_ep0_zlp(struct s3c_udc *dev) { u32 ep_ctrl; flush_dcache_range((unsigned long) usb_ctrl_dma_addr, (unsigned long) usb_ctrl_dma_addr + DMA_BUFFER_SIZE); writel(usb_ctrl_dma_addr, ®->in_endp[EP0_CON].diepdma); writel(DIEPT_SIZ_PKT_CNT(1), ®->in_endp[EP0_CON].dieptsiz); ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, ®->in_endp[EP0_CON].diepctl); DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n", __func__, readl(®->in_endp[EP0_CON].diepctl)); dev->ep0state = WAIT_FOR_IN_COMPLETE; }
/* * elfin usb client interrupt handler. */ static irqreturn_t s3c_udc_irq(int irq, void *_dev) { struct s3c_udc *dev = _dev; u32 intr_status; u32 usb_status, ep_ctrl, gintmsk; spin_lock(&dev->lock); intr_status = readl(S3C_UDC_OTG_GINTSTS); gintmsk = readl(S3C_UDC_OTG_GINTMSK); DEBUG_ISR("\n**** %s : GINTSTS=0x%x(on state %s), GINTMSK : 0x%x\n", __FUNCTION__, intr_status, state_names[dev->ep0state], gintmsk); if (!intr_status) { spin_unlock(&dev->lock); return IRQ_HANDLED; } if (intr_status & INT_ENUMDONE) { DEBUG_SETUP("####################################\n"); DEBUG_SETUP(" %s: Speed Detection interrupt\n", __FUNCTION__); writel(INT_ENUMDONE, S3C_UDC_OTG_GINTSTS); usb_status = (readl(S3C_UDC_OTG_DSTS) & 0x6); if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ)) { DEBUG_SETUP(" %s: Full Speed Detection\n",__FUNCTION__); set_max_pktsize(dev, USB_SPEED_FULL); } else { DEBUG_SETUP(" %s: High Speed Detection : 0x%x\n", __FUNCTION__, usb_status); set_max_pktsize(dev, USB_SPEED_HIGH); } } if (intr_status & INT_EARLY_SUSPEND) { DEBUG_SETUP("####################################\n"); DEBUG_SETUP(" %s:Early suspend interrupt\n", __FUNCTION__); writel(INT_EARLY_SUSPEND, S3C_UDC_OTG_GINTSTS); } if (intr_status & INT_SUSPEND) { usb_status = readl(S3C_UDC_OTG_DSTS); DEBUG_SETUP("####################################\n"); DEBUG_SETUP(" %s:Suspend interrupt :(DSTS):0x%x\n", __FUNCTION__, usb_status); writel(INT_SUSPEND, S3C_UDC_OTG_GINTSTS); if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver && dev->driver->suspend) { dev->driver->suspend(&dev->gadget); } } if (intr_status & INT_RESUME) { DEBUG_SETUP("####################################\n"); DEBUG_SETUP(" %s: Resume interrupt\n", __FUNCTION__); writel(INT_RESUME, S3C_UDC_OTG_GINTSTS); if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver && dev->driver->resume) { dev->driver->resume(&dev->gadget); } } if (intr_status & INT_RESET) { usb_status = readl(S3C_UDC_OTG_GOTGCTL); DEBUG_SETUP("####################################\n"); DEBUG_SETUP(" %s: Reset interrupt - (GOTGCTL):0x%x\n", __FUNCTION__, usb_status); writel(INT_RESET, S3C_UDC_OTG_GINTSTS); if((usb_status & 0xc0000) == (0x3 << 18)) { if(reset_available) { DEBUG_SETUP(" ===> OTG core got reset (%d)!! \n", reset_available); reconfig_usbd(); dev->ep0state = WAIT_FOR_SETUP; reset_available = 0; } } else { reset_available = 1; DEBUG_SETUP(" RESET handling skipped : reset_available : %d\n", reset_available); } } if (intr_status & INT_RX_FIFO_NOT_EMPTY) { u32 grx_status, packet_status, ep_num, fifoCntByte = 0; /* Mask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */ gintmsk &= ~INT_RX_FIFO_NOT_EMPTY; writel(gintmsk, S3C_UDC_OTG_GINTMSK); grx_status = readl(S3C_UDC_OTG_GRXSTSR); DEBUG_ISR(" INT_RX_FIFO_NOT_EMPTY(GRXSTSR):0x%x, GINTMSK:0x%x\n", grx_status, gintmsk); packet_status = grx_status & 0x1E0000; fifoCntByte = (grx_status & 0x7ff0)>>4; ep_num = grx_status & EP_MASK; if (fifoCntByte) { if (packet_status == SETUP_PKT_RECEIVED) { DEBUG_EP0(" => A SETUP data packet received : %d bytes\n", fifoCntByte); s3c_handle_ep0(dev); /* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */ gintmsk |= INT_RX_FIFO_NOT_EMPTY; } else if (packet_status == OUT_PKT_RECEIVED) { if(ep_num == EP1_OUT) { ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL1); DEBUG_ISR(" => A Bulk OUT data packet received : %d bytes, (DOEPCTL1):0x%x\n", fifoCntByte, ep_ctrl); s3c_out_epn(dev, 1); gintmsk = readl(S3C_UDC_OTG_GINTMSK); writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL1); } else if (ep_num == EP0_CON) { ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0); DEBUG_EP0(" => A CONTROL OUT data packet received : %d bytes, (DOEPCTL0):0x%x\n", fifoCntByte, ep_ctrl); dev->ep0state = DATA_STATE_RECV; s3c_ep0_read(dev); gintmsk |= INT_RX_FIFO_NOT_EMPTY; } else { DEBUG_ISR(" => Unused EP: %d bytes, (GRXSTSR):0x%x\n", fifoCntByte, grx_status); } } else { grx_status = readl(S3C_UDC_OTG_GRXSTSP); /* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */ gintmsk |= INT_RX_FIFO_NOT_EMPTY; DEBUG_ISR(" => A reserved packet received : %d bytes\n", fifoCntByte); } } else { if (dev->ep0state == DATA_STATE_XMIT) { ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0); DEBUG_EP0(" => Write ep0 continue... (DOEPCTL0):0x%x\n", ep_ctrl); s3c_ep0_write(dev); } if (packet_status == SETUP_TRANSACTION_COMPLETED) { ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0); DEBUG_EP0(" => A SETUP transaction completed (DOEPCTL0):0x%x\n", ep_ctrl); writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL0); } else if (packet_status == OUT_TRANSFER_COMPLELTED) { if (ep_num == EP1_OUT) { ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL1); DEBUG_ISR(" => An OUT transaction completed (DOEPCTL1):0x%x\n", ep_ctrl); writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL1); } else if (ep_num == EP0_CON) { ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0); DEBUG_ISR(" => An OUT transaction completed (DOEPCTL0):0x%x\n", ep_ctrl); writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL0); } else { DEBUG_ISR(" => Unused EP: %d bytes, (GRXSTSR):0x%x\n", fifoCntByte, grx_status); } } else if (packet_status == OUT_PKT_RECEIVED) { DEBUG_ISR(" => A OUT PACKET RECEIVED (NO FIFO CNT BYTE)...(GRXSTSR):0x%x\n", grx_status); } else { DEBUG_ISR(" => A RESERVED PACKET RECEIVED (NO FIFO CNT BYTE)...(GRXSTSR):0x%x\n", grx_status); } grx_status = readl(S3C_UDC_OTG_GRXSTSP); /* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */ gintmsk |= INT_RX_FIFO_NOT_EMPTY; } /* Un/Mask USB OTG 2.0 interrupt sources */ writel(gintmsk, S3C_UDC_OTG_GINTMSK); spin_unlock(&dev->lock); return IRQ_HANDLED; }
/* Inline code */ static __inline__ int write_packet(struct s3c_ep *ep, struct s3c_request *req, int max) { u32 *buf; int length, count; u32 fifo = ep->fifo, in_ctrl; buf = req->req.buf + req->req.actual; prefetch(buf); length = req->req.length - req->req.actual; length = min(length, max); req->req.actual += length; DEBUG("%s: Write %d (max %d), fifo=0x%x\n", __FUNCTION__, length, max, fifo); if(ep_index(ep) == EP0_CON) { writel((1<<19)|(length<<0), (u32) S3C_UDC_OTG_DIEPTSIZ0); in_ctrl = readl(S3C_UDC_OTG_DIEPCTL0); writel(DEPCTL_EPENA|DEPCTL_CNAK|(EP2_IN<<11)| in_ctrl, (u32) S3C_UDC_OTG_DIEPCTL0); DEBUG_EP0("%s:(DIEPTSIZ0):0x%x, (DIEPCTL0):0x%x, (GNPTXSTS):0x%x\n", __FUNCTION__, readl(S3C_UDC_OTG_DIEPTSIZ0),readl(S3C_UDC_OTG_DIEPCTL0), readl(S3C_UDC_OTG_GNPTXSTS)); udelay(30); } else if ((ep_index(ep) == EP2_IN)) { writel((1<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ2); in_ctrl = readl(S3C_UDC_OTG_DIEPCTL2); writel(DEPCTL_EPENA|DEPCTL_CNAK|(EP2_IN<<11)| in_ctrl, (u32) S3C_UDC_OTG_DIEPCTL2); DEBUG_IN_EP("%s:(DIEPTSIZ2):0x%x, (DIEPCTL2):0x%x, (GNPTXSTS):0x%x\n", __FUNCTION__, readl(S3C_UDC_OTG_DIEPTSIZ2),readl(S3C_UDC_OTG_DIEPCTL2), readl(S3C_UDC_OTG_GNPTXSTS)); udelay(30); } else if ((ep_index(ep) == EP3_IN)) { if (set_interface_first == 1) { DEBUG_IN_EP("%s: first packet write skipped after set_interface\n", __FUNCTION__); set_interface_first = 0; return length; } writel((1<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ3); in_ctrl = readl(S3C_UDC_OTG_DIEPCTL3); writel(DEPCTL_EPENA|DEPCTL_CNAK|(EP2_IN<<11)| in_ctrl, (u32) S3C_UDC_OTG_DIEPCTL3); DEBUG_IN_EP("%s:(DIEPTSIZ3):0x%x, (DIEPCTL3):0x%x, (GNPTXSTS):0x%x\n", __FUNCTION__, readl(S3C_UDC_OTG_DIEPTSIZ3),readl(S3C_UDC_OTG_DIEPCTL3), readl(S3C_UDC_OTG_GNPTXSTS)); udelay(30); } else { printk("%s: --> Error Unused Endpoint!!\n", __FUNCTION__); BUG(); } for (count = 0; count < length; count += 4) writel(*buf++, fifo); return length; }