/* * wmt_udc.c -- for WonderMedia Technology udc * * Copyright (C) 2007 VIA Technologies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #undef DEBUG #undef VERBOSE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "udc_wmt.h" #define USE_BULK3_TO_INTERRUPT //gri //#define FULL_SPEED_ONLY /*#define HW_BUG_HIGH_SPEED_PHY*/ #undef USB_TRACE /* bulk DMA seems to be behaving for both IN and OUT */ #define USE_DMA /*#define DEBUG_UDC_ISR_TIMER*/ #undef DEBUG_UDC_ISR_TIMER /*#define RNDIS_INFO_DEBUG_BULK_OUT*/ #undef RNDIS_INFO_DEBUG_BULK_OUT /*#define RNDIS_INFO_DEBUG_BULK_IN*/ #undef RNDIS_INFO_DEBUG_BULK_IN /*#define MSC_COMPLIANCE_TEST*/ #undef MSC_COMPLIANCE_TEST /*#define UDC_A1_SELF_POWER_ENABLE*/ /*-----------------------------------------------------------------------------*/ #define DRIVER_DESC "VIA UDC driver" #define DRIVER_VERSION "3 December 2007" #define DMA_ADDR_INVALID (~(dma_addr_t)0) static unsigned fifo_mode; static unsigned fiq_using = 0; /* "modprobe vt8500_udc fifo_mode=42", or else as a kernel * boot parameter "vt8500_udc:fifo_mode=42" */ module_param(fifo_mode, uint, 0); MODULE_PARM_DESC(fifo_mode, "endpoint setup (0 == default)"); static bool use_dma = 1; module_param(use_dma, bool, 0); MODULE_PARM_DESC(use_dma, "enable/disable DMA"); static const char driver_name[] = "wmotgdev";/*"wmt_udc";*/ static const char driver_desc[] = DRIVER_DESC; static DEFINE_SEMAPHORE(wmt_udc_sem); static int f_ep3_used = 0; static struct vt8500_udc *udc; static struct device *pDMADescLI, *pDMADescSI; static struct device *pDMADescLO, *pDMADescSO; static struct device *pDMADescL2I, *pDMADescS2I; dma_addr_t UdcPdmaPhyAddrLI, UdcPdmaPhyAddrSI; static UINT UdcPdmaVirAddrLI, UdcPdmaVirAddrSI; dma_addr_t UdcPdmaPhyAddrLO, UdcPdmaPhyAddrSO; static UINT UdcPdmaVirAddrLO, UdcPdmaVirAddrSO; dma_addr_t UdcPdmaPhyAddrL2I, UdcPdmaPhyAddrS2I; static UINT UdcPdmaVirAddrL2I, UdcPdmaVirAddrS2I; dma_addr_t UdcRndisEp1PhyAddr, UdcRndisEp2PhyAddr, UdcRndisEp3PhyAddr; static UINT UdcRndisEp1VirAddr, UdcRndisEp2VirAddr, UdcRndisEp3VirAddr; #ifdef OTGIP static struct USB_GLOBAL_REG *pGlobalReg; #endif /*static struct UDC_REGISTER *udc_reg;*/ static volatile struct UDC_REGISTER *pDevReg; static volatile struct UDC_DMA_REG *pUdcDmaReg; PSETUPCOMMAND pSetupCommand; UCHAR *pSetupCommandBuf; UCHAR *SetupBuf; UCHAR *IntBuf; UCHAR ControlState; /* the state the control pipe*/ UCHAR USBState; UCHAR TestMode; /* Basic Define*/ //#define REG32 *(volatile unsigned int *) //#define REG_GET32(addr) (REG32(addr)) /* Read 32 bits Register */ static unsigned long irq_flags;//gri volatile unsigned char *pUSBMiscControlRegister5; unsigned int interrupt_transfer_size; static void wmt_pdma_reset(void); static void wmt_pdma0_reset(void); static void wmt_pdma1_reset(void); #ifdef USE_BULK3_TO_INTERRUPT static void wmt_pdma2_reset(void); #endif /* 1 : storage */ static unsigned int gadget_connect=0; //static unsigned int first_mount=0; struct work_struct online_thread; struct work_struct offline_thread; struct work_struct done_thread; struct work_struct chkiso_thread; struct list_head done_main_list; spinlock_t gri_lock; static unsigned long gri_flags;//gri static unsigned int b_pullup=0; void run_chkiso (struct work_struct *work); static inline unsigned int wmt_ost_counter(void) { OSTC_VAL |= OSTC_RDREQ; while (OSTA_VAL & OSTA_RCA) ; return (u32)OSCR_VAL; } static inline void wmt_ost2_set_match(u32 new_match) { /* check if can write OS Timer2 match register nows */ while (OSTA_VAL & OSTA_MWA2) ; OSM2_VAL = new_match; } void wmt_enable_fiq(unsigned int how_many_us) { unsigned int cnt = 0; cnt = wmt_ost_counter(); cnt += (3*how_many_us); wmt_ost2_set_match(cnt); OSTI_VAL |= OSTI_E2; } void wmt_disable_fiq(void) { OSTI_VAL &= ~OSTI_E2; } static irqreturn_t test_fiq_handler(int irq, void *_udc)//, struct pt_regs *r) { OSTS_VAL = OSTI_E2; //printk("i am test_fiq_handler\n"); run_chkiso(NULL); return IRQ_HANDLED; } void initial_test_fiq(void) { //int ret = -1; int status = -ENODEV; printk("\n\n\ninitial_test_fiq\n\n"); // set fiq OSTS_VAL = OSTI_E2; OSTI_VAL &= ~OSTI_E2; #if 0 fhandler.fiq = test_fiq_handler; fhandler.resume = test_fiq_resume; ret = fiq_wmt_register_handler(&fhandler); if (ret) { pr_err("%s: could not install fiq handler ( %d )\n", __func__, ret); return; } //use OST2 to test enable_fiq(70); #else status = request_irq(IRQ_OST2, test_fiq_handler, // (SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM), driver_name, udc); // (IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM), driver_name, udc); (IRQF_DISABLED), driver_name, udc);//gri if (status != 0) { ERR("**** can't get irq %d, err %d\n", IRQ_OST2, status); } else INFO("**** wmt_udc_probe - request_irq(0x%02X) pass!\n", IRQ_OST2); #endif } /** * * Run these two functions to execute shell script to mount / umount storage * */ #if 0 static int run_online(void) { kobject_uevent(&udc->dev->kobj, 2); return 0; } #endif void wmt_cleanup_done_thread(int number); static void run_offline (struct work_struct *work) { if ((udc->driver) && b_pullup){ // printk(KERN_INFO "disconnect\n"); //gri udc->driver->disconnect(&udc->gadget); } // return 0; } static void run_done (struct work_struct *work) { struct vt8500_req * req; spin_lock_irqsave(&gri_lock, gri_flags); // printk(KERN_INFO "d1\n"); //gri while (!list_empty(&done_main_list)){ // printk(KERN_INFO "d3\n"); //gri req = list_entry(done_main_list.next, struct vt8500_req, mem_list); list_del_init(&req->mem_list); spin_unlock_irqrestore(&gri_lock, gri_flags); req->req.complete(&req->ep->ep, &req->req); spin_lock_irqsave(&gri_lock, gri_flags); } // printk(KERN_INFO "d2\n"); //gri spin_unlock_irqrestore(&gri_lock, gri_flags); // return 0; } void dma_irq(u8 addr); void next_in_dma(struct vt8500_ep *ep, struct vt8500_req *req); void iso_prepare_0byte(void); void run_chkiso (struct work_struct *work) { spin_lock_irqsave(&udc->lock, irq_flags); if (!fiq_using) { //printk("iso fail\n"); spin_unlock_irqrestore(&udc->lock, irq_flags); return; } //do { //schedule(); if (pDevReg->Bulk3DesStatus & BULKXFER_XACTERR) { { struct vt8500_ep *ep; struct vt8500_req *req; /*u32 temp32;*/ /*u32 i;*/ ep = &udc->ep[4]; if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); //printk("iso h q\n"); next_in_dma(ep, req); } else { //printk("no q\n"); wmt_disable_fiq(); fiq_using = 0; wmt_pdma2_reset(); iso_prepare_0byte(); } } //printk("iso hit\n"); //break; } else { wmt_enable_fiq(300); //printk("iso hit miss\n"); } //} while (1); spin_unlock_irqrestore(&udc->lock, irq_flags); } enum schedule_work_action { action_done, action_off_line, action_chkiso }; static void run_script(enum schedule_work_action dwAction) { if (dwAction == action_done){//8 schedule_work(&done_thread); }else if (dwAction == action_off_line){//7 schedule_work(&offline_thread); }else if (dwAction == action_chkiso){//7 schedule_work(&chkiso_thread); }else { } } void udc_device_dump_register(void) { volatile unsigned int address; volatile unsigned char temp8; int i; for (i = 0x20; i <= 0x3F; i++) { /*0x20~0x3F (0x3F-0x20 + 1) /4 = 8 DWORD*/ address = (USB_UDC_REG_BASE + i); temp8 = REG_GET8(address); INFO("[UDC Device] Offset[0x%8.8X] = 0x%2.2X \n", address, temp8); } for (i = 0x308; i <= 0x30D; i++) { /*0x308~0x30D*/ address = (USB_UDC_REG_BASE + i); temp8 = REG_GET8(address); INFO("[UDC Device] Offset[0x%8.8X] = 0x%2.2X \n", address, temp8); } for (i = 0x310; i <= 0x317; i++) { /*0x310~0x317*/ address = (USB_UDC_REG_BASE + i); temp8 = REG_GET8(address); INFO("[UDC Device] Offset[0x%8.8X] = 0x%2.2X \n", address, temp8); } INFO("[UDC Device] Dump Reigster PASS!\n"); } /*void udc_device_dump_register(void)*/ void udc_bulk_dma_dump_register(void) { volatile unsigned int temp32; int i; for (i = 0; i <= 0x10; i++) { /*0x100 ~ 0x113 (0x113 - 0x100 + 1) = 0x14 /4 = 5*/ temp32 = REG_GET32(USB_UDC_DMA_REG_BASE + i*4); INFO("[UDC Bulk DMA] Offset[0x%8.8X] = 0x%8.8X \n", (USB_UDC_DMA_REG_BASE + i*4), temp32); } INFO("[UDC Bulk DMAD] Dump Reigster PASS!\n"); } /*void udc_bulk_dma_dump_register(void)*/ void wmt_ep_setup_csr(char *name, u8 addr, u8 type, unsigned maxp) { struct vt8500_ep *ep; /*u32 epn_rxtx = 0;*/ /*U8 temp_adr;*/ VDBG("wmt_ep_setup_csr()\n"); /* OUT endpoints first, then IN*/ ep = &udc->ep[addr & 0x7f]; VDBG("wmt_ep_setup()\n"); /* OUT endpoints first, then IN*/ ep = &udc->ep[addr & 0x7f]; if (type == USB_ENDPOINT_XFER_CONTROL) { /*pDevReg->ControlEpControl;*/ pDevReg->ControlEpReserved = 0; pDevReg->ControlEpMaxLen = (maxp & 0xFF); pDevReg->ControlEpEpNum = 0; } else if (type == USB_ENDPOINT_XFER_BULK) { if (addr & USB_DIR_IN) { /*pDevReg->Bulk1EpControl;*/ pDevReg->Bulk1EpOutEpNum = (addr & 0x7f) << 4; pDevReg->Bulk1EpMaxLen = (maxp & 0xFF); pDevReg->Bulk1EpInEpNum = (((addr & 0x7f) << 4) | ((maxp & 0x700) >> 8)); } else { /*pDevReg->Bulk2EpControl;*/ pDevReg->Bulk2EpOutEpNum = (addr & 0x7f) << 4; pDevReg->Bulk2EpMaxLen = (maxp & 0xFF); pDevReg->Bulk2EpInEpNum = (((addr & 0x7f) << 4) | ((maxp & 0x700) >> 8)); } } else if (type == USB_ENDPOINT_XFER_INT) { #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpOutEpNum = (addr & 0x7f) << 4; pDevReg->Bulk3EpMaxLen = (maxp & 0xFF); pDevReg->Bulk3EpInEpNum = (((addr & 0x7f) << 4) | ((maxp & 0x700) >> 8)); pDevReg->InterruptReserved = (0x85 & 0x7f) << 4; pDevReg->InterruptEpMaxLen = (8 & 0xFF); /* Interrupt maximum transfer length - 2E*/ pDevReg->InterruptEpEpNum = (((0x85 & 0x7f) << 4) | ((8 & 0x700) >> 8)); #else /*pDevReg->InterruptEpControl; // Interrupt endpoint control - 2C*/ /* Interrupt endpoint reserved byte - 2D*/ pDevReg->InterruptReserved = (addr & 0x7f) << 4; pDevReg->InterruptEpMaxLen = (maxp & 0xFF); /* Interrupt maximum transfer length - 2E*/ pDevReg->InterruptEpEpNum = (((addr & 0x7f) << 4) | ((maxp & 0x700) >> 8)); #endif } else if (type == USB_ENDPOINT_XFER_ISOC) { pDevReg->Bulk3EpOutEpNum = (addr & 0x7f) << 4; pDevReg->Bulk3EpMaxLen = (maxp & 0xFF); pDevReg->Bulk3EpInEpNum = (((addr & 0x7f) << 4) | ((maxp & 0x700) >> 8)); } /*Setting address pointer ...*/ wmb(); VDBG("wmt_ep_setup_csr() - %s addr %02x maxp %d\n", name, addr, maxp); ep->toggle_bit = 0; ep->ep.maxpacket = maxp; } /*tatic void wmt_ep_setup_csr()*/ static int wmt_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { struct vt8500_ep *ep = container_of(_ep, struct vt8500_ep, ep); struct vt8500_udc *udc; u16 maxp; DBG("wmt_ep_enable() %s\n", ep ? ep->ep.name : NULL); printk(KERN_INFO "gri wmt_ep_enable() %s\n", ep ? ep->ep.name : NULL); /* catch various bogus parameters*/ if (!_ep || !desc || (ep->desc && ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC)) || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->maxpacket < usb_endpoint_maxp(desc)) { VDBG("ep->bEndpointAddress = 0x%08X\n", ep->bEndpointAddress); VDBG("desc->bEndpointAddres = 0x%08X\n", desc->bEndpointAddress); VDBG("ep->maxpacket =0x%08X\n", ep->maxpacket); VDBG("desc->wMaxPacketSize =0x%08X\n", desc->wMaxPacketSize); VDBG("_ep =0x%08X\n", (unsigned int)_ep); VDBG("desc =0x%08X\n", (unsigned int)desc); VDBG("ep->desc =0x%08X\n", (unsigned int)ep->desc); /*DBG("%s, bad ep or descriptor\n", __FUNCTION__);*/ return -EINVAL; } maxp = usb_endpoint_maxp(desc); if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK) && (usb_endpoint_maxp(desc) > ep->maxpacket || !desc->wMaxPacketSize)) { DBG("[wmt_ep_enable]bad %s maxpacket\n", _ep->name); return -ERANGE; } #if 1 if ((desc->bmAttributes == USB_ENDPOINT_XFER_ISOC && desc->bInterval != 1)) { /* hardware wants period = 1; USB allows 2^(Interval-1) */ DBG("%s, unsupported ISO period %dms\n", _ep->name, 1 << (desc->bInterval - 1)); return -EDOM; } #if 0 /* xfer types must match, except that interrupt ~= bulk*/ if (ep->bmAttributes != desc->bmAttributes && ep->bmAttributes != USB_ENDPOINT_XFER_BULK && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { DBG("[wmt_ep_enable], %s type mismatch\n", _ep->name); printk("[wmt_ep_enable], %s type mismatch\n", _ep->name); return -EINVAL; } #endif #endif udc = ep->udc; spin_lock_irqsave(&udc->lock, irq_flags); ep->desc = desc; ep->irqs = 0; ep->stopped = 0; ep->ep.maxpacket = maxp; ep->has_dma = 1; ep->ackwait = 0; switch ((ep->bEndpointAddress & 0x7F)) { case 0:/*Control In/Out*/ wmt_ep_setup_csr("ep0", 0, USB_ENDPOINT_XFER_CONTROL, 64); wmb(); pDevReg->ControlEpControl = EP_RUN + EP_ENABLEDMA; break; case 1:/*Bulk In*/ wmt_ep_setup_csr("ep1in-bulk", (USB_DIR_IN | 1), USB_ENDPOINT_XFER_BULK, maxp); wmb(); pDevReg->Bulk1EpControl = EP_RUN + EP_ENABLEDMA; break; case 2:/*Bulk Out*/ wmt_ep_setup_csr("ep2out-bulk", (USB_DIR_OUT | 2), USB_ENDPOINT_XFER_BULK, maxp); wmb(); pDevReg->Bulk2EpControl = EP_RUN + EP_ENABLEDMA; break; case 3:/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT if (f_ep3_used == 4) return -ERANGE; f_ep3_used = 3; wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, maxp); wmb(); pDevReg->Bulk3EpControl = EP_RUN + EP_ENABLEDMA; #else wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, maxp); wmb(); pDevReg->InterruptEpControl = EP_RUN + EP_ENABLEDMA; #endif break; case 4:/*iso in*/ if (f_ep3_used == 3) return -ERANGE; f_ep3_used = 4; wmt_ep_setup_csr("ep4in-iso", (USB_DIR_IN | 4), USB_ENDPOINT_XFER_ISOC, 384); wmb(); wmt_pdma2_reset(); iso_prepare_0byte(); pDevReg->Bulk3EpControl = EP_RUN + EP_ENABLEDMA; break; } wmb(); spin_unlock_irqrestore(&udc->lock, irq_flags); VDBG("%s enabled\n", _ep->name); // printk(KERN_INFO "gri enabled %s\n", ep ? ep->ep.name : NULL); return 0; } /*static int wmt_ep_enable()*/ static void nuke(struct vt8500_ep *, int status); static int wmt_ep_disable(struct usb_ep *_ep) { struct vt8500_ep *ep = container_of(_ep, struct vt8500_ep, ep); // unsigned long flags; DBG("wmt_ep_disable() %s\n", ep ? ep->ep.name : NULL); if (!_ep || !ep->desc) { DBG("[wmt_ep_disable], %s not enabled\n", _ep ? ep->ep.name : NULL); return -EINVAL; } spin_lock_irqsave(&ep->udc->lock, irq_flags); ep->desc = 0; nuke(ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; ep->has_dma = 0; del_timer(&ep->timer); switch ((ep->bEndpointAddress & 0x7F)) { case 0:/*Control In/Out*/ pDevReg->ControlEpControl &= 0xFC; break; case 1:/*Bulk In*/ pDevReg->Bulk1EpControl &= 0xFC; break; case 2:/*Bulk Out*/ pDevReg->Bulk2EpControl &= 0xFC; break; case 3:/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT if (f_ep3_used == 3) f_ep3_used = 0; pDevReg->Bulk3EpControl &= 0xFC; #else pDevReg->InterruptEpControl &= 0xFC; #endif break; case 4:/*Iso In*/ if (f_ep3_used == 4) f_ep3_used = 0; pDevReg->Bulk3EpControl &= 0xFC; fiq_using = 0; break; } wmb(); spin_unlock_irqrestore(&ep->udc->lock, irq_flags); VDBG("%s disabled\n", _ep->name); return 0; } /*static int wmt_ep_disable()*/ static struct usb_request * wmt_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) { struct vt8500_req *req; struct vt8500_ep *ep = NULL; // DBG("gri wmt_alloc_request() %s\n", ep->name); ep = container_of(_ep, struct vt8500_ep, ep); // printk(KERN_INFO "gri wmt_alloc_request() %s\n", ep->name); // if ((ep->bEndpointAddress & 0x7F) > 4) // return NULL; /*if(ep->bEndpointAddress == 3)*/ /* INFO("wmt_alloc_request() %s\n", ep->name);*/ req = kmalloc(sizeof *req, gfp_flags); if (req) { memset(req, 0, sizeof *req); req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); } return &req->req;/*struct usb_request for file_storage.o*/ } /*wmt_alloc_request()*/ static void wmt_free_request(struct usb_ep *_ep, struct usb_request *_req) { struct vt8500_req *req = container_of(_req, struct vt8500_req, req); struct vt8500_ep *ep = NULL; DBG("wmt_free_request() %s\n", ep->name); ep = container_of(_ep, struct vt8500_ep, ep); /*if(ep->bEndpointAddress == 3)*/ /* INFO("wmt_free_request() %s\n", ep->name);*/ if (_req) kfree(req); } /*wmt_free_request()*/ /*EP0 - Control 256 bytes*/ /*EP2,3 Bulk In/Out 16384 bytes (16K)*/ /*file_storeage.c - req->buf*/ /*struct usb_request req;*/ static void wmt_pdma_init(struct device *dev); static void ep0_status(struct vt8500_udc *udc) { struct vt8500_ep *ep; ep = &udc->ep[0]; if (udc->ep0_in) { /*OUT STATUS*/ if (udc->ep0_status_0_byte == 1) { udc->ep0_status_0_byte = 0; /* the data phase is OUT*/ if (ep->toggle_bit) pDevReg->ControlDesTbytes = 0x40|CTRLXFER_DATA1; else pDevReg->ControlDesTbytes = 0x40|CTRLXFER_DATA0; pDevReg->ControlDesControl = CTRLXFER_OUT+CTRLXFER_IOC; wmb(); pDevReg->ControlDesStatus = CTRLXFER_ACTIVE; ControlState = CONTROLSTATE_STATUS; } /*if(udc->ep0_status_0_byte == 1)*/ } else { /*IN STATUS*/ if (udc->ep0_status_0_byte == 1) { udc->ep0_status_0_byte = 0; if (ep->toggle_bit) pDevReg->ControlDesTbytes = 0x00 | CTRLXFER_DATA1; else pDevReg->ControlDesTbytes = 0x00 | CTRLXFER_DATA0; pDevReg->ControlDesTbytes = 0x00 | CTRLXFER_DATA1; /* zero length*/ pDevReg->ControlDesControl = CTRLXFER_IN + CTRLXFER_IOC; wmb(); pDevReg->ControlDesStatus = CTRLXFER_ACTIVE; ControlState = CONTROLSTATE_STATUS; } /*if(udc->ep0_status_0_byte == 1)*/ } } /*static void ep0_status(struct vt8500_udc *udc)*/ static void done(struct vt8500_ep *ep, struct vt8500_req *req, int status) { unsigned stopped = ep->stopped; DBG("done() %s\n", ep ? ep->ep.name : NULL); list_del_init(&req->queue); /*#define EINPROGRESS 115*/ /* Operation now in progress */ if (req->req.status == -EINPROGRESS) req->req.status = status; else { if (status != 0) status = req->req.status; } DBG("complete %s req %p stat %d len %u/%u\n", ep->ep.name, &req->req, status, req->req.actual, req->req.length); /* don't modify queue heads during completion callback*/ ep->stopped = 1; spin_unlock_irqrestore(&ep->udc->lock, irq_flags); req->req.complete(&ep->ep, &req->req); spin_lock_irqsave(&ep->udc->lock, irq_flags); if ((ep->bEndpointAddress & 0x7F) == 0)/*Control*/ { if (req->req.actual != 0) { ep->udc->ep0_status_0_byte = 1; } } #if 0 else printk("**done() %s\n", ep ? ep->ep.name : NULL); #endif ep->stopped = stopped; } /*done(struct vt8500_ep *ep, struct vt8500_req *req, int status)*/ static u32 dma_src_len(struct vt8500_ep *ep, struct vt8500_req *req) { /*dma_addr_t end;*/ /*U32 ep_trans_len;*/ unsigned start = 0 , end = 0; u32 temp32 = 0; start = req->req.length; if ((ep->bEndpointAddress & 0x7F) == 0) {/*Control In*/ end = (pDevReg->ControlDesTbytes & 0x7F); temp32 = (ep->ep_fifo_length - end); return temp32; } else if ((ep->bEndpointAddress & 0x7F) == 1) {/*Bulk In*/ end = (pDevReg->Bulk1DesTbytes2 & 0x03) << 16; end |= pDevReg->Bulk1DesTbytes1 << 8; end |= pDevReg->Bulk1DesTbytes0; } else if ((ep->bEndpointAddress & 0x7F) == 3)/*Interrupt In*/ { #ifdef USE_BULK3_TO_INTERRUPT end = (pDevReg->Bulk3DesTbytes2 & 0x03) << 16; end |= pDevReg->Bulk3DesTbytes1 << 8; end |= pDevReg->Bulk3DesTbytes0; #else start = req->dma_bytes; end = (pDevReg->InterruptDes >> 4); #endif } else if ((ep->bEndpointAddress & 0x7F) == 4)/*Iso In*/ { end = 0; } temp32 = (start - end); return temp32; } /*static u32 dma_src_len()*/ static u32 dma_dest_len(struct vt8500_ep *ep, struct vt8500_req *req) { /*dma_addr_t end;*/ unsigned start = 0 , end = 0; u32 temp32 = 0; start = req->req.length; if ((ep->bEndpointAddress & 0x7F) == 0) {/*Control Out*/ end = (pDevReg->ControlDesTbytes & 0x7F); temp32 = (ep->ep_fifo_length - end); return temp32; } else if (ep->bEndpointAddress == 2) {/*Bulk Out*/ end = (pDevReg->Bulk2DesTbytes2 & 0x03) << 16; end |= pDevReg->Bulk2DesTbytes1 << 8; end |= pDevReg->Bulk2DesTbytes0; } temp32 = (start - end); return temp32; } /*static u32 dma_dest_len()*/ /* Each USB transfer request using DMA maps to one or more DMA transfers. * When DMA completion isn't request completion, the UDC continues with * the next DMA transfer for that USB transfer. */ static void wmt_udc_pdma_des_prepare(unsigned int size, unsigned int dma_phy , unsigned char des_type, unsigned char channel, int is_bulk) { unsigned int res_size = size; volatile unsigned int trans_dma_phy = dma_phy, des_phy_addr = 0, des_vir_addr = 0; unsigned int cut_size = 0x40; switch (des_type) { case DESCRIPTOT_TYPE_SHORT: { struct _UDC_PDMA_DESC_S *pDMADescS; if (channel == TRANS_OUT) { des_phy_addr = (unsigned int) UdcPdmaPhyAddrSO; des_vir_addr = UdcPdmaVirAddrSO; pUdcDmaReg->DMA_Descriptor_Point1 = (unsigned int)(des_phy_addr); cut_size = pDevReg->Bulk2EpMaxLen & 0x3ff; } else if (channel == TRANS_IN) { if (is_bulk) { des_phy_addr = (unsigned int) UdcPdmaPhyAddrSI; des_vir_addr = UdcPdmaVirAddrSI; pUdcDmaReg->DMA_Descriptor_Point0 = (unsigned int)(des_phy_addr); cut_size = pDevReg->Bulk1EpMaxLen & 0x3ff; } else { des_phy_addr = (unsigned int) UdcPdmaPhyAddrS2I; des_vir_addr = UdcPdmaVirAddrS2I; pUdcDmaReg->DMA_Descriptor_Point2 = (unsigned int)(des_phy_addr); cut_size = pDevReg->Bulk3EpMaxLen & 0x3ff; } } else DBG("!! wrong channel %d\n", channel); while (res_size) { pDMADescS = (struct _UDC_PDMA_DESC_S *) des_vir_addr; pDMADescS->Data_Addr = trans_dma_phy; pDMADescS->D_Word0_Bits.Format = 0; // if (res_size <= 65535) { if (res_size <= 32767) { pDMADescS->D_Word0_Bits.i = 1; pDMADescS->D_Word0_Bits.End = 1; pDMADescS->D_Word0_Bits.ReqCount = res_size; res_size -= res_size; } else { pDMADescS->D_Word0_Bits.i = 0; pDMADescS->D_Word0_Bits.End = 0; pDMADescS->D_Word0_Bits.ReqCount = 0x8000 - cut_size; res_size -= 0x8000; des_vir_addr += (unsigned int)DES_S_SIZE; trans_dma_phy += (unsigned int)0x8000; } } break; } case DESCRIPTOT_TYPE_LONG: { struct _UDC_PDMA_DESC_L *pDMADescL; if (channel == TRANS_OUT) { des_phy_addr = (unsigned int) UdcPdmaPhyAddrLO; des_vir_addr = UdcPdmaVirAddrLO; pUdcDmaReg->DMA_Descriptor_Point1 = (unsigned int)(des_phy_addr); cut_size = pDevReg->Bulk2EpMaxLen & 0x3ff; // printk(KERN_INFO "wmt_udc_pdma_des_prepare() pUdcDmaReg->DMA_Descriptor_Point=0x%08X", // pUdcDmaReg->DMA_Descriptor_Point1); //gri // printk(KERN_INFO "des_vir_addr=0x%08X", // des_vir_addr); //gri } else if (channel == TRANS_IN) { if (is_bulk){ des_phy_addr = (unsigned int) UdcPdmaPhyAddrLI; des_vir_addr = UdcPdmaVirAddrLI; pUdcDmaReg->DMA_Descriptor_Point0 = (unsigned int)(des_phy_addr); cut_size = pDevReg->Bulk1EpMaxLen & 0x3ff; // printk(KERN_INFO "wmt_udc_pdma_des_prepare() pUdcDmaReg->DMA_Descriptor_Point=0x%08X", // pUdcDmaReg->DMA_Descriptor_Point0); //gri // printk(KERN_INFO "des_vir_addr=0x%08X", // des_vir_addr); //gri } else { des_phy_addr = (unsigned int) UdcPdmaPhyAddrL2I; des_vir_addr = UdcPdmaVirAddrL2I; pUdcDmaReg->DMA_Descriptor_Point2 = (unsigned int)(des_phy_addr); cut_size = pDevReg->Bulk3EpMaxLen & 0x3ff; // printk(KERN_INFO "wmt_udc_pdma_des_prepare() pUdcDmaReg->DMA_Descriptor_Point2=0x%08X", // pUdcDmaReg->DMA_Descriptor_Point2); //gri // printk(KERN_INFO "des_vir_addr 2 =0x%08X", // des_vir_addr); //gri } } else DBG("!! wrong channel %d\n", channel); memset((void *)des_vir_addr, 0, 0x100); while (res_size) { pDMADescL = (struct _UDC_PDMA_DESC_L *) des_vir_addr; pDMADescL->Data_Addr = trans_dma_phy; pDMADescL->D_Word0_Bits.Format = 1; // if (res_size <= 65535) { if (res_size <= 32767) { pDMADescL->D_Word0_Bits.i = 1; pDMADescL->D_Word0_Bits.End = 1; pDMADescL->Branch_addr = 0; pDMADescL->D_Word0_Bits.ReqCount = res_size; res_size -= res_size; } else { pDMADescL->D_Word0_Bits.i = 0; pDMADescL->D_Word0_Bits.End = 0; pDMADescL->Branch_addr = des_vir_addr + (unsigned int)DES_L_SIZE; pDMADescL->D_Word0_Bits.ReqCount = 0x8000 - cut_size; res_size -= 0x8000; des_vir_addr += (unsigned int)DES_L_SIZE; trans_dma_phy += (unsigned int)0x8000; } } #if 0 if (channel == TRANS_IN) { if (!is_bulk) { printk(KERN_INFO "pDMADescL(0x%08X)\n", des_vir_addr); //gri printk(KERN_INFO "D_Word0(0x%08X)\n", pDMADescL->D_Word0); //gri printk(KERN_INFO "Data_Addr(0x%08X)\n", pDMADescL->Data_Addr); //gri printk(KERN_INFO "Branch_addr(0x%08X)\n", pDMADescL->Branch_addr); //gri } else { printk(KERN_INFO "pDMADescL(0x%08X)\n", des_vir_addr); //gri printk(KERN_INFO "D_Word0(0x%08X)\n", pDMADescL->D_Word0); //gri printk(KERN_INFO "Data_Addr(0x%08X)\n", pDMADescL->Data_Addr); //gri printk(KERN_INFO "Branch_addr(0x%08X)\n", pDMADescL->Branch_addr); //gri } } #endif break; } case DESCRIPTOT_TYPE_MIX: break; default: break; } //wmb(); } /*wmt_udc_pdma_des_prepare*/ void iso_prepare_0byte(void) { unsigned char ubulk3tmp; ubulk3tmp = pDevReg->Bulk3EpControl; pDevReg->Bulk3EpControl = EP_DMALIGHTRESET; while (pDevReg->Bulk3EpControl & EP_DMALIGHTRESET) ; pDevReg->Bulk3DesStatus = 0; pDevReg->Bulk3DesTbytes2 = 0; pDevReg->Bulk3DesTbytes1 = 0; pDevReg->Bulk3DesTbytes0 = 0; pDevReg->Bulk3EpControl = ubulk3tmp; /* set endpoint data toggle*/ pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); //wmb(); pDevReg->Bulk3DesStatus |= BULKXFER_ACTIVE; } void next_in_dma(struct vt8500_ep *ep, struct vt8500_req *req) { u32 temp32; u32 dma_ccr = 0; unsigned int length; u32 dcmd; u32 buf; int is_in, i; u8 *pctrlbuf; #ifndef USE_BULK3_TO_INTERRUPT u8 *pintbuf; #endif // printk(KERN_INFO "next_in_dma s\n"); //gri dcmd = length = req->req.length - req->req.actual;/*wmt_ep_queue() : req->req.actual = 0*/ buf = ((req->req.dma + req->req.actual) & 0xFFFFFFFC); is_in = 1;/*ep->bEndpointAddress & USB_DIR_IN;*/ DBG("next_in_dma() %s\n", ep ? ep->ep.name : NULL); #ifdef RNDIS_INFO_DEBUG_BULK_IN if ((ep->bEndpointAddress & 0x7F) == 1) INFO("next_in_dma() %s\n", ep ? ep->ep.name : NULL); #endif if (((ep->bEndpointAddress & 0x7F) == 1) && (req->req.dma == 0xFFFFFFFF) && (ep->rndis == 0)) { unsigned int dma_length = 65536; printk(KERN_INFO "rndis xxxxx %d\n",req->req.length); if (ep->rndis_buffer_alloc == 0) { ep->rndis_buffer_address = (unsigned int)UdcRndisEp1VirAddr; ep->rndis_dma_phy_address = (u32)UdcRndisEp1PhyAddr; ep->rndis_buffer_length = dma_length; ep->rndis_buffer_alloc = 1; } ep->rndis = 1; } #ifdef USE_BULK3_TO_INTERRUPT if (((ep->bEndpointAddress & 0x7F) == 3) && (req->req.dma == 0xFFFFFFFF) && (ep->rndis == 0)) { unsigned int dma_length = 65536; //printk(KERN_INFO "rndis 3 xxxxx %d\n",req->req.length); if (ep->rndis_buffer_alloc == 0) { ep->rndis_buffer_address = (unsigned int)UdcRndisEp3VirAddr; ep->rndis_dma_phy_address = (u32)UdcRndisEp3PhyAddr; ep->rndis_buffer_length = dma_length; ep->rndis_buffer_alloc = 1; } ep->rndis = 1; } #endif if (((ep->bEndpointAddress & 0x7F) == 4) && (req->req.dma == 0xFFFFFFFF) && (ep->rndis == 0)) { unsigned int dma_length = 65536; //printk(KERN_INFO "rndis 3 xxxxx %d\n",req->req.length); if (ep->rndis_buffer_alloc == 0) { ep->rndis_buffer_address = (unsigned int)UdcRndisEp3VirAddr; ep->rndis_dma_phy_address = (u32)UdcRndisEp3PhyAddr; ep->rndis_buffer_length = dma_length; ep->rndis_buffer_alloc = 1; } ep->rndis = 1; } if (((ep->bEndpointAddress & 0x7F) == 1) && (ep->rndis == 1) && (req->req.length > ep->rndis_buffer_length)) { //void *retval; //dma_addr_t dma; printk(KERN_INFO "rndis ooooobb %d\n",req->req.length); } #ifdef USE_BULK3_TO_INTERRUPT if (((ep->bEndpointAddress & 0x7F) == 3) && (ep->rndis == 1) && (req->req.length > ep->rndis_buffer_length)) { //void *retval; //dma_addr_t dma; //printk(KERN_INFO "rndis 3 ooooobb %d\n",req->req.length); } #endif if ((ep->bEndpointAddress & 0x7F) == 0) {/*Control*/ ep->ep_fifo_length = 0; if (length >= 64) length = 64; ep->ep_fifo_length = length; pctrlbuf = (u8 *)(req->req.buf + req->req.actual); for (i = 0; i < length; i++) SetupBuf[i] = pctrlbuf[i]; if (ep->toggle_bit) pDevReg->ControlDesTbytes = length | CTRLXFER_DATA1; else pDevReg->ControlDesTbytes = length | CTRLXFER_DATA0; pDevReg->ControlDesControl = CTRLXFER_IN + CTRLXFER_IOC; wmb(); pDevReg->ControlDesStatus = CTRLXFER_ACTIVE; ControlState = CONTROLSTATE_DATA; if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; } else if (((ep->bEndpointAddress & 0x7F) == 1)) {/*Bulk In*/ ep->stall_more_processing = 0; // printk(KERN_INFO "next_in_dma %d %d %d\n", length, req->req.length,req->req.actual); //gri if (dcmd > UBE_MAX_DMA) dcmd = UBE_MAX_DMA; if (pDevReg->Bulk1EpControl & EP_STALL) { ep->stall_more_processing = 1; ep->temp_dcmd = dcmd; } if (ep->rndis == 1) { memcpy((void *)((u32)ep->rndis_buffer_address), (void *)((u32)req->req.buf), length); wmt_udc_pdma_des_prepare(dcmd, ((ep->rndis_dma_phy_address + req->req.actual) & 0xFFFFFFFC), DESCRIPTOT_TYPE_LONG, TRANS_IN, 1); } else wmt_udc_pdma_des_prepare(dcmd, buf, DESCRIPTOT_TYPE_LONG, TRANS_IN, 1); if (pDevReg->Bulk1EpControl & EP_STALL) ep->temp_bulk_dma_addr = buf; if (pDevReg->Bulk1EpControl & EP_STALL) ep->temp_dma_ccr = dma_ccr; pDevReg->Bulk1DesStatus = 0x00; pDevReg->Bulk1DesTbytes2 |= (dcmd >> 16) & 0x3; pDevReg->Bulk1DesTbytes1 = (dcmd >> 8) & 0xFF; pDevReg->Bulk1DesTbytes0 = dcmd & 0xFF; /* set endpoint data toggle*/ if (is_in) { if (ep->toggle_bit) pDevReg->Bulk1DesTbytes2 |= 0x40;/* BULKXFER_DATA1;*/ else pDevReg->Bulk1DesTbytes2 &= 0xBF;/*(~BULKXFER_DATA1);*/ pDevReg->Bulk1DesStatus = (BULKXFER_IOC | BULKXFER_IN); } /*if(is_in)*/ if (pDevReg->Bulk1EpControl & EP_STALL) ep->ep_stall_toggle_bit = ep->toggle_bit; /*if((ep->bEndpointAddress & 0x7F) != 0)//!Control*/ if (req->req.length > ep->maxpacket) { /*ex : 512 /64 = 8 8 % 2 = 0*/ temp32 = (req->req.length + ep->maxpacket - 1) / ep->maxpacket; ep->toggle_bit = ((temp32 + ep->toggle_bit) % 2); } else { if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; } /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ dma_ccr = 0; dma_ccr = DMA_RUN; if (!is_in) dma_ccr |= DMA_TRANS_OUT_DIR; if (dcmd) /* PDMA can not support 0 byte transfer*/ pUdcDmaReg->DMA_Context_Control0 = dma_ccr; wmb(); pDevReg->Bulk1DesStatus |= BULKXFER_ACTIVE; } else if ((ep->bEndpointAddress & 0x7F) == 3) {/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT ep->stall_more_processing = 0; // printk(KERN_INFO "next_in_dma %d %d %d\n", length, req->req.length,req->req.actual); //gri if (dcmd > UBE_MAX_DMA) dcmd = UBE_MAX_DMA; if (pDevReg->Bulk3EpControl & EP_STALL) { ep->stall_more_processing = 1; ep->temp_dcmd = dcmd; } if (ep->rndis == 1) { memcpy((void *)((u32)ep->rndis_buffer_address), (void *)((u32)req->req.buf), length); wmt_udc_pdma_des_prepare(dcmd, ((ep->rndis_dma_phy_address + req->req.actual) & 0xFFFFFFFC), DESCRIPTOT_TYPE_LONG, TRANS_IN, 0); } else wmt_udc_pdma_des_prepare(dcmd, buf, DESCRIPTOT_TYPE_LONG, TRANS_IN, 0); if (pDevReg->Bulk3EpControl & EP_STALL) ep->temp_bulk_dma_addr = buf; if (pDevReg->Bulk3EpControl & EP_STALL) ep->temp_dma_ccr = dma_ccr; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes2 |= (dcmd >> 16) & 0x3; pDevReg->Bulk3DesTbytes1 = (dcmd >> 8) & 0xFF; pDevReg->Bulk3DesTbytes0 = dcmd & 0xFF; /* set endpoint data toggle*/ if (is_in) { if (ep->toggle_bit) pDevReg->Bulk3DesTbytes2 |= 0x40;/* BULKXFER_DATA1;*/ else pDevReg->Bulk3DesTbytes2 &= 0xBF;/*(~BULKXFER_DATA1);*/ pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); } /*if(is_in)*/ if (pDevReg->Bulk3EpControl & EP_STALL) ep->ep_stall_toggle_bit = ep->toggle_bit; /*if((ep->bEndpointAddress & 0x7F) != 0)//!Control*/ if (req->req.length > ep->maxpacket) { /*ex : 512 /64 = 8 8 % 2 = 0*/ temp32 = (req->req.length + ep->maxpacket - 1) / ep->maxpacket; ep->toggle_bit = ((temp32 + ep->toggle_bit) % 2); } else { if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; } /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ dma_ccr = 0; //dma_ccr = DMA_RUN; if (!is_in) dma_ccr |= DMA_TRANS_OUT_DIR; wmb(); if (dcmd) /* PDMA can not support 0 byte transfer*/ pUdcDmaReg->DMA_Context_Control2 = dma_ccr; dma_ccr |= DMA_RUN; wmb(); if (dcmd) /* PDMA can not support 0 byte transfer*/ pUdcDmaReg->DMA_Context_Control2 = dma_ccr; wmb(); pDevReg->Bulk3DesStatus |= BULKXFER_ACTIVE; #else //printk(KERN_INFO "udc interrupt\n"); if (dcmd > INT_FIFO_SIZE) dcmd = INT_FIFO_SIZE; interrupt_transfer_size = dcmd; pintbuf = (u8 *)(req->req.buf);/* + req->req.actual);*/ for (i = req->req.actual; i < (req->req.actual + dcmd); i++) IntBuf[(i-req->req.actual)] = pintbuf[i]; pDevReg->InterruptDes = 0x00; pDevReg->InterruptDes = (dcmd << 4); if (ep->toggle_bit) pDevReg->InterruptDes |= INTXFER_DATA1; else pDevReg->InterruptDes &= 0xF7; if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; pDevReg->InterruptDes |= INTXFER_IOC; wmb(); pDevReg->InterruptDes |= INTXFER_ACTIVE; #endif } else if ((ep->bEndpointAddress & 0x7F) == 4) {/*Iso In*/ unsigned char tmp; tmp = pDevReg->Bulk3EpControl; pDevReg->Bulk3EpControl = EP_DMALIGHTRESET; while (pDevReg->Bulk3EpControl & EP_DMALIGHTRESET) ; pDevReg->Bulk3EpControl = tmp; wmt_pdma2_reset(); ep->stall_more_processing = 0; //printk(KERN_INFO "next_in_dma 4 %d %d %d\n", length, req->req.length,req->req.actual); //gri //printk(KERN_INFO "next_in_dma 4\n"); //gri if (dcmd > UBE_MAX_DMA) dcmd = UBE_MAX_DMA; if (pDevReg->Bulk3EpControl & EP_STALL) { ep->stall_more_processing = 1; ep->temp_dcmd = dcmd; } if (ep->rndis == 1) { memcpy((void *)((u32)ep->rndis_buffer_address), (void *)((u32)req->req.buf), length); wmt_udc_pdma_des_prepare(dcmd, ((ep->rndis_dma_phy_address + req->req.actual) & 0xFFFFFFFC), DESCRIPTOT_TYPE_LONG, TRANS_IN, 0); } else wmt_udc_pdma_des_prepare(dcmd, buf, DESCRIPTOT_TYPE_LONG, TRANS_IN, 0); if (pDevReg->Bulk3EpControl & EP_STALL) ep->temp_bulk_dma_addr = buf; if (pDevReg->Bulk3EpControl & EP_STALL) ep->temp_dma_ccr = dma_ccr; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes2 |= (dcmd >> 16) & 0x3; pDevReg->Bulk3DesTbytes1 = (dcmd >> 8) & 0xFF; pDevReg->Bulk3DesTbytes0 = dcmd & 0xFF; /* set endpoint data toggle*/ if (is_in) { pDevReg->Bulk3DesTbytes2 &= 0xBF;/*(~BULKXFER_DATA1);*/ pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); } /*if(is_in)*/ if (pDevReg->Bulk3EpControl & EP_STALL) ep->ep_stall_toggle_bit = ep->toggle_bit; /*if((ep->bEndpointAddress & 0x7F) != 0)//!Control*/ ep->toggle_bit = 0; /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ dma_ccr = 0; //dma_ccr = DMA_RUN; if (!is_in) dma_ccr |= DMA_TRANS_OUT_DIR; // wmb(); if (dcmd) /* PDMA can not support 0 byte transfer*/ pUdcDmaReg->DMA_Context_Control2 = dma_ccr; dma_ccr |= DMA_RUN; // wmb(); if (dcmd) /* PDMA can not support 0 byte transfer*/ pUdcDmaReg->DMA_Context_Control2 = dma_ccr; // wmb(); pDevReg->Bulk3DesStatus |= BULKXFER_ACTIVE; fiq_using = 1; wmt_enable_fiq(300); //run_script(action_chkiso); } DBG("req->req.dma 0x%08X \n", req->req.dma); #ifdef MSC_COMPLIANCE_TEST INFO("req->req.dma 0x%08X \n", req->req.dma); #endif req->dma_bytes = dcmd;//length; #if 0 if (((ep->bEndpointAddress & 0x7F) == 3) || ((ep->bEndpointAddress & 0x7F) == 4)) { printk(KERN_INFO "next_in_dma 3 e\n"); //gri printk(KERN_INFO "Bulk3EpInEpNum =0x%2.2x\n", pDevReg->Bulk3EpInEpNum); //gri printk(KERN_INFO "Bulk3EpMaxLen =0x%2.2x\n", pDevReg->Bulk3EpMaxLen); //gri printk(KERN_INFO "Bulk3EpOutEpNum =0x%2.2x\n", pDevReg->Bulk3EpOutEpNum); //gri printk(KERN_INFO "Bulk3EpControl =0x%2.2x\n", pDevReg->Bulk3EpControl); //gri printk(KERN_INFO "Bulk3DesTbytes2 =0x%2.2x\n", pDevReg->Bulk3DesTbytes2); //gri printk(KERN_INFO "Bulk3DesTbytes1 =0x%2.2x\n", pDevReg->Bulk3DesTbytes1); //gri printk(KERN_INFO "Bulk3DesTbytes0 =0x%2.2x\n", pDevReg->Bulk3DesTbytes0); //gri printk(KERN_INFO "Bulk3DesStatus =0x%2.2x\n", pDevReg->Bulk3DesStatus); //gri printk(KERN_INFO "DMA_Descriptor_Point2 =0x%8.8x\n", pUdcDmaReg->DMA_Descriptor_Point2); //gri printk(KERN_INFO "DMA_Residual_Bytes2 =0x%8.8x\n", pUdcDmaReg->DMA_Residual_Bytes2); //gri printk(KERN_INFO "DMA_Data_Addr2 =0x%8.8x\n", pUdcDmaReg->DMA_Data_Addr2); //gri printk(KERN_INFO "DMA_Branch_Addr2 =0x%8.8x\n", pUdcDmaReg->DMA_Branch_Addr2); //gri printk(KERN_INFO "Descriptor_Addr2 =0x%8.8x\n", pUdcDmaReg->Descriptor_Addr2); //gri printk(KERN_INFO "DMA_Context_Control2 =0x%8.8x\n", pUdcDmaReg->DMA_Context_Control2); //gri } else if ((ep->bEndpointAddress & 0x7F) == 1) { printk(KERN_INFO "next_in_dma 1 e\n"); //gri printk(KERN_INFO "Bulk1EpInEpNum =0x%2.2x\n", pDevReg->Bulk1EpInEpNum); //gri printk(KERN_INFO "Bulk1EpMaxLen =0x%2.2x\n", pDevReg->Bulk1EpMaxLen); //gri printk(KERN_INFO "Bulk1EpOutEpNum =0x%2.2x\n", pDevReg->Bulk1EpOutEpNum); //gri printk(KERN_INFO "Bulk1EpControl =0x%2.2x\n", pDevReg->Bulk1EpControl); //gri printk(KERN_INFO "Bulk1DesTbytes2 =0x%2.2x\n", pDevReg->Bulk1DesTbytes2); //gri printk(KERN_INFO "Bulk1DesTbytes1 =0x%2.2x\n", pDevReg->Bulk1DesTbytes1); //gri printk(KERN_INFO "Bulk1DesTbytes0 =0x%2.2x\n", pDevReg->Bulk1DesTbytes0); //gri printk(KERN_INFO "Bulk1DesStatus =0x%2.2x\n", pDevReg->Bulk1DesStatus); //gri printk(KERN_INFO "DMA_Descriptor_Point2 =0x%8.8x\n", pUdcDmaReg->DMA_Descriptor_Point0); //gri printk(KERN_INFO "DMA_Residual_Bytes2 =0x%8.8x\n", pUdcDmaReg->DMA_Residual_Bytes0); //gri printk(KERN_INFO "DMA_Data_Addr2 =0x%8.8x\n", pUdcDmaReg->DMA_Data_Addr0); //gri printk(KERN_INFO "DMA_Branch_Addr2 =0x%8.8x\n", pUdcDmaReg->DMA_Branch_Addr0); //gri printk(KERN_INFO "Descriptor_Addr2 =0x%8.8x\n", pUdcDmaReg->Descriptor_Addr0); //gri printk(KERN_INFO "DMA_Context_Control2 =0x%8.8x\n", pUdcDmaReg->DMA_Context_Control0); //gri } #endif } /*static void next_in_dma()*/ static void finish_in_dma(struct vt8500_ep *ep, struct vt8500_req *req, int status) { // printk(KERN_INFO "finish_in_dma()s\n"); //gri DBG("finish_in_dma() %s\n", ep ? ep->ep.name : NULL); if (status == 0) { /* Normal complete!*/ #ifdef USE_BULK3_TO_INTERRUPT req->req.actual += dma_src_len(ep, req);/*req->dma_bytes;*/ #else // if ((ep->bEndpointAddress & 0x7F) == 3) // req->req.actual += interrupt_transfer_size; // else if ((ep->bEndpointAddress & 0x7F) != 3) req->req.actual += dma_src_len(ep, req);/*req->dma_bytes;*/ #endif /* return if this request needs to send data or zlp*/ if (req->req.actual < req->req.length) return; if (req->req.zero && req->dma_bytes != 0 && (req->req.actual % ep->maxpacket) == 0) return; } else req->req.actual += dma_src_len(ep, req); #ifdef RNDIS_INFO_DEBUG_BULK_IN if ((ep->bEndpointAddress & 0x7F) == 1) INFO("finish_in_dma()e %s req->req.actual(0x%08X) req->req.length(0x%08X)\n", ep ? ep->ep.name : NULL, req->req.actual, req->req.length); #endif done(ep, req, status); //printk(KERN_INFO "finish_in_dma() %s req->req.actual(0x%08X) req->req.length(0x%08X)\n", //ep ? ep->ep.name : NULL, req->req.actual, req->req.length); //gri } /*static void finish_in_dma()*/ static void next_out_dma(struct vt8500_ep *ep, struct vt8500_req *req) { /*unsigned packets;*/ u32 dma_ccr = 0; u32 dcmd; u32 buf; int is_in; // printk(KERN_INFO "next_out_dma s\n"); //gri is_in = 0;/*ep->bEndpointAddress & USB_DIR_IN;*/ #ifdef RNDIS_INFO_DEBUG_BULK_OUT if (ep->bEndpointAddress == 2) INFO("next_out_dma() %s\n", ep ? ep->ep.name : NULL); #endif DBG("next_out_dma() %s\n", ep ? ep->ep.name : NULL); dcmd = req->dma_bytes = req->req.length - req->req.actual; buf = ((req->req.dma + req->req.actual) & 0xFFFFFFFC); if ((ep->bEndpointAddress == 2) && (req->req.dma == 0xFFFFFFFF) && (ep->rndis == 0)) { unsigned int dma_length = 65536; printk(KERN_INFO "rndis ooooo %d\n",req->req.length); if (ep->rndis_buffer_alloc == 0) { ep->rndis_buffer_address = (unsigned int)UdcRndisEp2VirAddr; ep->rndis_dma_phy_address = (u32)UdcRndisEp2PhyAddr; ep->rndis_buffer_length = dma_length; ep->rndis_buffer_alloc = 1; } ep->rndis = 1; } if ((ep->bEndpointAddress == 2) && (ep->rndis == 1) && (req->req.length > ep->rndis_buffer_length)) { // void *retval; // dma_addr_t dma; printk(KERN_INFO "rndis ooooobb %d\n",req->req.length); #if 0 dma_free_coherent (ep->udc->dev, ep->rndis_buffer_length, (void *)ep->rndis_buffer_address, (dma_addr_t)ep->rndis_dma_phy_address); retval = dma_alloc_coherent(ep->udc->dev, req->req.length, &dma, GFP_ATOMIC); ep->rndis_buffer_address = (unsigned int)retval; ep->rndis_dma_phy_address = (u32)dma; ep->rndis_buffer_length = req->req.length; ep->rndis = 1; #endif } if (ep->bEndpointAddress == 0) {/*Control*/ ep->ep_fifo_length = 0; if (dcmd >= 64) dcmd = 64; ep->ep_fifo_length = dcmd; if (ep->toggle_bit) pDevReg->ControlDesTbytes = dcmd | CTRLXFER_DATA1; else pDevReg->ControlDesTbytes = dcmd | CTRLXFER_DATA0; pDevReg->ControlDesControl = CTRLXFER_OUT+CTRLXFER_IOC; wmb(); pDevReg->ControlDesStatus = CTRLXFER_ACTIVE; ControlState = CONTROLSTATE_DATA; if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; } else if (ep->bEndpointAddress == 2) {/*Bulk Out*/ ep->stall_more_processing = 0; // printk(KERN_INFO "next_out_dma %d %d %d\n", req->dma_bytes, req->req.length,req->req.actual); //gri /*if(req->dma_bytes == 64)*/ ep->udc->cbw_virtual_address = (((u32)req->req.buf + req->req.actual) & 0xFFFFFFFC); if (dcmd > UBE_MAX_DMA) dcmd = UBE_MAX_DMA; if (pDevReg->Bulk2EpControl & EP_STALL) { ep->stall_more_processing = 1; ep->temp_dcmd = dcmd; } /* Set Address*/ if (ep->rndis == 1) wmt_udc_pdma_des_prepare(dcmd, ((ep->rndis_dma_phy_address + req->req.actual) & 0xFFFFFFFC), DESCRIPTOT_TYPE_LONG, TRANS_OUT, 1); else wmt_udc_pdma_des_prepare(dcmd, buf, DESCRIPTOT_TYPE_LONG, TRANS_OUT, 1); if (pDevReg->Bulk2EpControl & EP_STALL) ep->temp_bulk_dma_addr = buf; if (pDevReg->Bulk2EpControl & EP_STALL) ep->temp_dma_ccr = dma_ccr; /* DMA Global Controller Reg*/ /* DMA Controller Enable +*/ /* DMA Global Interrupt Enable(if any TC, error, or abort status in any channels occurs)*/ pDevReg->Bulk2DesStatus = 0x00; pDevReg->Bulk2DesTbytes2 |= (dcmd >> 16) & 0x3; pDevReg->Bulk2DesTbytes1 = (dcmd >> 8) & 0xFF; pDevReg->Bulk2DesTbytes0 = dcmd & 0xFF; /* set endpoint data toggle*/ if (ep->toggle_bit) pDevReg->Bulk2DesTbytes2 |= BULKXFER_DATA1; else pDevReg->Bulk2DesTbytes2 &= 0x3F;/*BULKXFER_DATA0;*/ pDevReg->Bulk2DesStatus = BULKXFER_IOC;/*| BULKXFER_IN;*/ if (pDevReg->Bulk2EpControl & EP_STALL) ep->ep_stall_toggle_bit = ep->toggle_bit; dma_ccr = 0; dma_ccr = DMA_RUN; if (!is_in) dma_ccr |= DMA_TRANS_OUT_DIR; wmb(); pUdcDmaReg->DMA_Context_Control1 = dma_ccr; wmb(); pDevReg->Bulk2DesStatus |= BULKXFER_ACTIVE; /*udc_device_dump_register();*/ } VDBG("req->req.dma 0x%08X \n", req->req.dma); //printk(KERN_INFO "next_out_dma e\n"); //gri } /*static void next_out_dma()*/ static void finish_out_dma(struct vt8500_ep *ep, struct vt8500_req *req, int status) { u16 count; u8 temp8; u32 temp32; /*u8 bulk_dma_csr;*/ // printk(KERN_INFO "finish_out_dma s\n"); //gri DBG("finish_out_dma() %s\n", ep ? ep->ep.name : NULL); count = dma_dest_len(ep, req); if (ep->bEndpointAddress == 0) {/*Control*/ u8 *pctrlbuf; int i; pctrlbuf = (u8 *)(req->req.buf + req->req.actual); for (i = 0; i < count; i++) pctrlbuf[i] = SetupBuf[i]; /*INFO("finish_out_dma() %s\n", ep ? ep->ep.name : NULL);*/ /*dump_bulk_buffer((req->req.buf + req->req.actual), count);*/ } count += req->req.actual; if (count <= req->req.length) req->req.actual = count; if (ep->bEndpointAddress == 0) {/*Control*/ if (req->req.actual < req->req.length) { temp8 = pDevReg->ControlDesStatus; if ((temp8 & CTRLXFER_SHORTPKT) == 0) return; /*Continue...*/ } } else if (ep->bEndpointAddress == 2) { if (pDevReg->Bulk2DesTbytes2 & 0x80) ep->toggle_bit= 1; else ep->toggle_bit= 0; // while((pUdcDmaReg->DMA_Context_Control1_Bis.EventCode != 0xf) && // (pUdcDmaReg->DMA_Context_Control1_Bis.EventCode != 0x5)); // printk(KERN_INFO "finish_out_dma() %s req->actual(%d) req->length(%d) toggle_bit(%8x) add %x\n", // ep ? ep->ep.name : NULL, req->req.actual, req->req.length, (pDevReg->Bulk2DesTbytes2), (unsigned int)pDevReg);//gri // INFO("finish_out_dma() %s req->actual(%d) req->length(%d) toggle_bit(%8x) add %x\n", // ep ? ep->ep.name : NULL, req->req.actual, req->req.length, (pDevReg->Bulk2DesTbytes2), (unsigned int)pDevReg); { { unsigned int gri_t_d; unsigned int gri_count=0; unsigned int dma_count; do{ gri_t_d=pUdcDmaReg->DMA_ISR ; gri_t_d &= 0x2; gri_count++; if (gri_count & 0x10){ gri_count=0; // printk(KERN_INFO "pUdcDmaReg->DMA_Context_Control1 0x%08x\n", &(pUdcDmaReg->DMA_Context_Control1)); printk(KERN_INFO "XXXXXXXXXXX 0x%08x\n",pUdcDmaReg->DMA_Context_Control1); dma_count = req->req.length - pUdcDmaReg->DMA_Residual_Bytes1_Bits.ResidualBytes; // printk(KERN_INFO "CC 0x%08x 0x%08x\n", dma_count, count); if (pUdcDmaReg->DMA_Context_Control1_Bis.Run == 0) break; if ((count == dma_count) || (count == 0)){ // printk(KERN_INFO "XXXXXXXXXXX 0x%08x\n",pUdcDmaReg->DMA_Context_Control1); // printk(KERN_INFO "CC 0x%08x 0x%08x\n", dma_count, count); // while(1); pUdcDmaReg->DMA_Context_Control1_Bis.Run = 0; break; } } }while(!gri_t_d); } } if (req->req.actual < req->req.length) { DBG("finish_out_dma() req->actual < req->req.length\n"); temp8 = pDevReg->Bulk2DesStatus; if ((temp8 & BULKXFER_SHORTPKT) == 0) return; /*Continue...*/ else { /*Short Package.*/ pDevReg->Bulk2EpControl |= EP_DMALIGHTRESET; wmb(); while (pDevReg->Bulk2EpControl & EP_DMALIGHTRESET) ; pDevReg->Bulk2EpControl = EP_RUN + EP_ENABLEDMA; wmb(); } } } /* rx completion*/ /*UDC_DMA_IRQ_EN_REG &= ~UDC_RX_EOT_IE(ep->dma_channel);*/ //#ifdef RNDIS_INFO_DEBUG_BULK_OUT // if (ep->bEndpointAddress == 2) // INFO("finish_out_dma() %s req->actual(%d) req->length(%d) toggle_bit(%8x) add %x\n", // ep ? ep->ep.name : NULL, req->req.actual, req->req.length, (pDevReg->Bulk2DesTbytes2), (unsigned int)pDevReg); //#endif /*dump_bulk_buffer(req->req.buf, req->req.actual);*/ if ((ep->bEndpointAddress == 2) && (ep->rndis == 1)) { memcpy((void *)((u32)req->req.buf), (void *)((u32)ep->rndis_buffer_address), req->req.actual); #ifdef RNDIS_INFO_DEBUG_BULK_OUT /*if ((req->req.actual % 4 == 3))// && (b_message == 0))*/ /*dump_bulk_buffer(req->req.buf, req->req.actual);*/ #endif #if 0 if ((req->req.length == 1600) || (req->req.length == 2048)) {/*F.S. [1600] : H.S. [2048]*/ /*ex : 512 /64 = 8 8 % 2 = 0*/ temp32 = (req->req.actual + ep->maxpacket - 1) / ep->maxpacket; ep->toggle_bit = ((temp32 + ep->toggle_bit) % 2); } else INFO("Different Length for Bulk Out (%08d) Toggle Bit would Error\n" , req->req.length); #else #if 0 if (req->req.length > ep->maxpacket) { /*ex : 512 /64 = 8 8 % 2 = 0*/ temp32 = (req->req.actual + ep->maxpacket - 1) / ep->maxpacket; ep->toggle_bit = ((temp32 + ep->toggle_bit) % 2); } else { if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; } #endif #endif } else { #if 1 if (ep->bEndpointAddress == 0){ /*GigaHsu-B 2008.5.15 : Add this caculate toggle from next_out_dma() : fixed sideshow gadget issue.*/ if (req->req.length > ep->maxpacket) { /*ex : 512 /64 = 8 8 % 2 = 0*/ temp32 = (req->req.actual + ep->maxpacket - 1) / ep->maxpacket; ep->toggle_bit = ((temp32 + ep->toggle_bit) % 2); } else { if (ep->toggle_bit == 0) ep->toggle_bit = 1; else ep->toggle_bit = 0; } } #endif /*GigaHsu-E 2008.5.15*/ } done(ep, req, status); //printk(KERN_INFO "finish_out_dma e\n"); //gri } /*finish_out_dma()*/ void dma_irq(u8 addr) { struct vt8500_ep *ep; struct vt8500_req *req; /*u32 temp32;*/ /*u32 i;*/ ep = &udc->ep[addr & 0x7f]; if ((ep->bEndpointAddress & 0x7F) == 1) {/*Bulk In*/ /* IN dma: tx to host*/ if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); finish_in_dma(ep, req, 0); } while (pDevReg->Bulk1EpControl & EP_COMPLETEINT) ; if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); next_in_dma(ep, req); } } else if (ep->bEndpointAddress == 2) {/*Bulk Out*/ /* OUT dma: rx from host*/ if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); finish_out_dma(ep, req, 0); } while (pDevReg->Bulk2EpControl & EP_COMPLETEINT) ; if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); next_out_dma(ep, req); } } else if ((ep->bEndpointAddress & 0x7F) == 3) {/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT /* IN dma: tx to host*/ if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); finish_in_dma(ep, req, 0); } while (pDevReg->Bulk3EpControl & EP_COMPLETEINT) ; if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); next_in_dma(ep, req); } #else /* IN dma: tx to host*/ while (pDevReg->InterruptEpControl & EP_COMPLETEINT) ; if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); req->req.actual += dma_src_len(ep, req); if (req->req.actual < req->req.length) next_in_dma(ep, req); else finish_in_dma(ep, req, 0); } // if (!list_empty(&ep->queue)) { // req = container_of(ep->queue.next, struct vt8500_req, queue); // next_in_dma(ep, req); // } #endif } else if ((ep->bEndpointAddress & 0x7F) == 4) {/*Iso In*/ /* IN dma: tx to host*/ if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); finish_in_dma(ep, req, 0); } } } /*static void dma_irq()*/ static void pullup_enable(struct vt8500_udc *udc) { INFO("gri pullup_enable()\n"); b_pullup = 1; /*Enable port control's FSM to enable 1.5k pull-up on D+.*/ //pDevReg->PhyMisc &= 0x0F;/*Hardware auto-mode*/ pDevReg->FunctionPatchEn |= 0x20; /* HW attach process evaluation enable bit*/ wmb(); /*pDevReg->PhyMisc |= 0x50;*/ } /*static void pullup_enable()*/ /*-------------------------------------------------------------------------*/ /*file_storage.c ep0_queue() - control*/ /*file_storage.c start_transfer() - bulk*/ static int wmt_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { struct vt8500_ep *ep = container_of(_ep, struct vt8500_ep, ep); struct vt8500_req *req = container_of(_req, struct vt8500_req, req); /*struct vt8500_udc *udc;*/ // unsigned long flags; unsigned char empty_data = 0; DBG("wmt_ep_queue() %s\n", ep ? ep->ep.name : NULL); // INFO("gri wmt_ep_queue() %s\n", ep ? ep->ep.name : NULL); // if ((ep->bEndpointAddress & 0x7F) > 4) // return -EINVAL; #ifdef RNDIS_INFO_DEBUG_BULK_OUT if ((ep->bEndpointAddress == 3))/* || ((ep->bEndpointAddress & 0x7F) == 2))*/ INFO("wmt_ep_queue() %s\n", ep ? ep->ep.name : NULL); #endif /* catch various bogus parameters*/ if (!_req || !req->req.complete || !req->req.buf || !list_empty(&req->queue)) { DBG("[wmt_ep_queue], bad params\n"); return -EINVAL; } if (!_ep || (!ep->desc && ep->bEndpointAddress)) { DBG("[wmt_ep_queue], bad ep\n"); return -EINVAL; } //#ifdef RNDIS_INFO_DEBUG_BULK_OUT // if ((ep->bEndpointAddress == 2))/* || ((ep->bEndpointAddress & 0x7F) == 1))*/ // INFO("wmt_ep_queue() %s queue req %p, len %d buf %p\n", // ep->ep.name, _req, _req->length, _req->buf); //#endif //#ifdef MSC_COMPLIANCE_TEST // if ((ep->bEndpointAddress & 0x7F) == 1) // INFO("wmt_ep_queue() %s queue req %p, len %d buf %p\n", // ep->ep.name, _req, _req->length, _req->buf); //#endif DBG("wmt_ep_queue() %s queue req %p, len %d buf %p\n", ep->ep.name, _req, _req->length, _req->buf); spin_lock_irqsave(&udc->lock, irq_flags); req->req.status = -EINPROGRESS; req->req.actual = 0; /* maybe kickstart non-iso i/o queues*/ if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) { int is_in; if (ep->bEndpointAddress == 0) { if (!udc->ep0_pending || !list_empty(&ep->queue)) { spin_unlock_irqrestore(&udc->lock, irq_flags); return -EL2HLT; } /* empty DATA stage?*/ is_in = udc->ep0_in; if (!req->req.length) { /*status 0 bytes*/ udc->ep0_status_0_byte = 1; ep0_status(udc); /* cleanup*/ udc->ep0_pending = 0; done(ep, req, 0); empty_data = 1; } if (req->req.length) { udc->bulk_out_dma_write_error = 0; (is_in ? next_in_dma : next_out_dma)(ep, req); } } else { is_in = ep->bEndpointAddress & USB_DIR_IN; if (req != 0){ list_add_tail(&req->queue, &ep->queue); empty_data = 1; } // else // { // printk(KERN_INFO "xxx %x %x\n",req,empty_data); //gri // } /*if (!ep->has_dma)*/ /* use_ep(ep, UDC_EP_SEL);*/ /* if ISO: SOF IRQs must be enabled/disabled!*/ if (((ep->bEndpointAddress & 0x7F) != 4) || (!fiq_using)) (is_in ? next_in_dma : next_out_dma)(ep, req); #if 0 else printk("gri w_e_q() 01 %s not q f_u=%d \n", ep ? ep->ep.name : NULL, fiq_using); #endif } } /* irq handler advances the queue*/ #if 0 if ((ep->bEndpointAddress & 0x7F) == 4) printk("gri w_e_q() 02 %s not q f_u=%d \n", ep ? ep->ep.name : NULL, fiq_using); #endif if ((req != 0) && (empty_data == 0)) list_add_tail(&req->queue, &ep->queue); spin_unlock_irqrestore(&udc->lock, irq_flags); return 0; } /*wmt_ep_queue()*/ void ep1_cancel_tx(struct vt8500_ep *ep) { unsigned char btmp; unsigned char bctrl0; bctrl0 = pDevReg->Bulk1EpControl & 0xE3; pDevReg->Bulk1DesStatus &= 0xF0; ep->stall_more_processing = 0; pDevReg->Bulk1DesStatus = 0x00; pDevReg->Bulk1DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk1DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk1DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ btmp = pDevReg->Bulk1DesTbytes2 & 0x40; if (btmp) ep->toggle_bit = 1; else ep->toggle_bit = 0; if (ep->toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk1DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk1DesTbytes2 &= 0xBF; } pDevReg->Bulk1DesStatus = (BULKXFER_IOC | BULKXFER_IN); wmb(); pDevReg->Bulk1EpControl |= EP_DMALIGHTRESET; wmb(); while (pDevReg->Bulk1EpControl & EP_DMALIGHTRESET); pDevReg->Bulk1EpControl = bctrl0; wmt_pdma0_reset(); wmb(); } void ep2_cancel_tx(struct vt8500_ep *ep) { unsigned char btmp; unsigned char bctrl0; bctrl0 = pDevReg->Bulk2EpControl & 0xE3; pDevReg->Bulk2DesStatus &= 0xF0; ep->stall_more_processing = 0; pDevReg->Bulk2DesStatus = 0x00; pDevReg->Bulk2DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk2DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk2DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ btmp = pDevReg->Bulk2DesTbytes2 & 0x80; if (btmp) ep->toggle_bit = 1; else ep->toggle_bit = 0; if (ep->toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk2DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk2DesTbytes2 &= 0xBF; } pDevReg->Bulk2DesStatus = (BULKXFER_IOC | BULKXFER_IN); wmb(); pDevReg->Bulk2EpControl |= EP_DMALIGHTRESET; wmb(); while (pDevReg->Bulk2EpControl & EP_DMALIGHTRESET); pDevReg->Bulk2EpControl = bctrl0; wmt_pdma1_reset(); wmb(); } void ep3_cancel_tx(struct vt8500_ep *ep) { #ifdef USE_BULK3_TO_INTERRUPT unsigned char btmp; unsigned char bctrl0; bctrl0 = pDevReg->Bulk3EpControl & 0xE3; pDevReg->Bulk3DesStatus &= 0xF0; ep->stall_more_processing = 0; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk3DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk3DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ btmp = pDevReg->Bulk3DesTbytes2 & 0x40; if (btmp) ep->toggle_bit = 1; else ep->toggle_bit = 0; if (ep->toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk3DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk3DesTbytes2 &= 0xBF; } pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); wmb(); pDevReg->Bulk3EpControl |= EP_DMALIGHTRESET; wmb(); while (pDevReg->Bulk3EpControl & EP_DMALIGHTRESET); pDevReg->Bulk3EpControl = bctrl0; wmt_pdma2_reset(); wmb(); #else unsigned char tmp0, tmp1, tmp2, tmp3; pDevReg->InterruptDes = 0x00; wmb(); tmp0 = InterruptEpControl; tmp1 = InterruptReserved; tmp2 = InterruptEpMaxLen; tmp3 = InterruptEpEpNum; InterruptEpControl |= EP_DMALIGHTRESET; wmb(); while (pDevReg->InterruptEpControl & EP_DMALIGHTRESET); InterruptEpControl = tmp0; InterruptReserved = tmp1; InterruptEpMaxLen = tmp2; InterruptEpEpNum = tmp3; wmb(); #endif } void ep4_cancel_tx(struct vt8500_ep *ep) { unsigned char btmp; unsigned char bctrl0; fiq_using = 0; bctrl0 = pDevReg->Bulk3EpControl & 0xE3; pDevReg->Bulk3DesStatus &= 0xF0; ep->stall_more_processing = 0; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk3DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk3DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ btmp = pDevReg->Bulk3DesTbytes2 & 0x40; if (btmp) ep->toggle_bit = 1; else ep->toggle_bit = 0; if (ep->toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk3DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk3DesTbytes2 &= 0xBF; } pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); wmb(); pDevReg->Bulk3EpControl |= EP_DMALIGHTRESET; wmb(); while (pDevReg->Bulk3EpControl & EP_DMALIGHTRESET); pDevReg->Bulk3EpControl = bctrl0; wmt_pdma2_reset(); wmb(); } static int wmt_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) { struct vt8500_ep *ep = container_of(_ep, struct vt8500_ep, ep); struct vt8500_req *req; int is_in; // unsigned long flags; if (!_ep || !_req) return -EINVAL; spin_lock_irqsave(&ep->udc->lock, irq_flags); DBG("wmt_ep_dequeue() %s\n", ep ? ep->ep.name : NULL); /* make sure it's actually queued on this endpoint*/ list_for_each_entry(req, &ep->queue, queue) { if (&req->req == _req) break; } if (&req->req != _req) { spin_unlock_irqrestore(&ep->udc->lock, irq_flags); return -EINVAL; } if (((ep->bEndpointAddress & 0x7F) != 0) && ep->queue.next == &req->queue) { if (ep->bEndpointAddress == 1){ ep1_cancel_tx(ep); } else if (ep->bEndpointAddress == 2){ ep2_cancel_tx(ep); } else if (ep->bEndpointAddress == 3){ ep3_cancel_tx(ep); } else if (ep->bEndpointAddress == 4){ ep4_cancel_tx(ep); } } done(ep, req, -ECONNRESET); if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); is_in = ep->bEndpointAddress & USB_DIR_IN; (is_in ? next_in_dma : next_out_dma)(ep, req); } spin_unlock_irqrestore(&ep->udc->lock, irq_flags); return 0; } /*static int wmt_ep_dequeue()*/ /*-------------------------------------------------------------------------*/ static int wmt_ep_set_halt(struct usb_ep *_ep, int value) { struct vt8500_ep *ep = container_of(_ep, struct vt8500_ep, ep); // unsigned long flags; int status = -EOPNOTSUPP; spin_lock_irqsave(&ep->udc->lock, irq_flags); ep->toggle_bit = 0; /*patch CLEAR_FEATURE ENDPOINT_HALT*/ DBG("wmt_ep_set_halt() %s\n", ep ? ep->ep.name : NULL); if (value) { u8 temp32bytes[31]; memset(temp32bytes, 0, 31); temp32bytes[0] = 0xEF; temp32bytes[1] = 0xBE; temp32bytes[2] = 0xAD; temp32bytes[3] = 0xDE; /*usb_ep_set_halt() - value == 1 stall*/ switch ((ep->bEndpointAddress & 0x7F)) { case 0:/*Control In/Out*/ pDevReg->ControlEpControl |= EP_STALL; break; case 1:/*Bulk In*/ pDevReg->Bulk1EpControl |= EP_STALL; break; case 2:/*Bulk Out*/ pDevReg->Bulk2EpControl |= EP_STALL; break; case 3:/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpControl |= EP_STALL; #else pDevReg->InterruptEpControl |= EP_STALL; #endif break; case 4:/*Iso In*/ pDevReg->Bulk3EpControl |= EP_STALL; break; } ep->stall = 1; /*DBG("wmt_ep_set_halt(1) HALT CSR(0x%08X)\n", *ep->reg_control_status);*/ status = 0; if (memcmp(temp32bytes, (void *)ep->udc->cbw_virtual_address, 4) == 0) udc->file_storage_set_halt = 1; /*forbid to CLEAR FEATURE*/ } else {/*usb_ep_clear_halt - value == 0 reset*/ /**ep->reg_control_status &= 0xFFFFFFFB;*/ switch ((ep->bEndpointAddress & 0x7F)) { case 0:/*Control In/Out*/ pDevReg->ControlEpControl &= 0xF7; break; case 1:/*Bulk In*/ pDevReg->Bulk1EpControl &= 0xF7; break; case 2:/*Bulk Out*/ pDevReg->Bulk2EpControl &= 0xF7; break; case 3:/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpControl &= 0xF7; #else pDevReg->InterruptEpControl &= 0xF7; #endif break; case 4:/*Iso In*/ pDevReg->Bulk3EpControl &= 0xF7; break; } ep->stall = 0; status = 0; udc->file_storage_set_halt = 0; } VDBG("%s %s halt stat %d\n", ep->ep.name, value ? "set" : "clear", status); wmb(); spin_unlock_irqrestore(&ep->udc->lock, irq_flags); return status; } /*static int wmt_ep_set_halt()*/ static struct usb_ep_ops wmt_ep_ops = { .enable = wmt_ep_enable, .disable = wmt_ep_disable, .alloc_request = wmt_alloc_request, .free_request = wmt_free_request, // .alloc_buffer = wmt_alloc_buffer, // .free_buffer = wmt_free_buffer, .queue = wmt_ep_queue, .dequeue = wmt_ep_dequeue, .set_halt = wmt_ep_set_halt, /* fifo_status ... report bytes in fifo*/ /* fifo_flush ... flush fifo*/ }; #if 0 static void wmt_udc_csr(struct vt8500_udc *udc) { /* abolish any previous hardware state*/ DBG("wmt_udc_csr()\n"); if (udc->gadget.speed == USB_SPEED_FULL) { wmt_ep_setup_csr("ep1in-bulk", (USB_DIR_IN | 1), USB_ENDPOINT_XFER_BULK, 64); wmt_ep_setup_csr("ep2out-bulk", (USB_DIR_OUT | 2), USB_ENDPOINT_XFER_BULK, 64); } else if (udc->gadget.speed == USB_SPEED_HIGH) { wmt_ep_setup_csr("ep1in-bulk", (USB_DIR_IN | 1), USB_ENDPOINT_XFER_BULK, 512); wmt_ep_setup_csr("ep2out-bulk", (USB_DIR_OUT | 2), USB_ENDPOINT_XFER_BULK, 512); } else if (udc->gadget.speed == USB_SPEED_UNKNOWN) { wmt_ep_setup_csr("ep1in-bulk", (USB_DIR_IN | 1), USB_ENDPOINT_XFER_BULK, 512); wmt_ep_setup_csr("ep2out-bulk", (USB_DIR_OUT | 2), USB_ENDPOINT_XFER_BULK, 512); } //wmt_ep_setup_csr("ep3in""-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 8); #ifdef USE_BULK3_TO_INTERRUPT wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 28); #else wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 8); #endif } /*wmt_udc_csr(void)*/ #endif static int wmt_get_frame(struct usb_gadget *gadget) { DBG("wmt_get_frame()\n"); return 0; } static int wmt_wakeup(struct usb_gadget *gadget) { /*struct vt8500_udc *udc;*/ /*unsigned long flags;*/ int retval = 0; DBG("wmt_wakeup()\n"); /* udc = container_of(gadget, struct vt8500_udc, gadget); spin_lock_irqsave(&udc->lock, irq_flags); if (udc->devstat & UDC_SUS) { // NOTE: OTG spec erratum says that OTG devices may // issue wakeups without host enable. // if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) { DBG("remote wakeup...\n"); UDC_SYSCON2_REG = UDC_RMT_WKP; retval = 0; } // NOTE: non-OTG systems may use SRP TOO... } else if (!(udc->devstat & UDC_ATT)) { if (udc->transceiver) retval = otg_start_srp(udc->transceiver->otg); } spin_unlock_irqrestore(&udc->lock, irq_flags); */ return retval; } static int wmt_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) { DBG("wmt_set_selfpowered()\n"); /* struct vt8500_udc *udc; unsigned long flags; u16 syscon1; udc = container_of(gadget, struct vt8500_udc, gadget); spin_lock_irqsave(&udc->lock, irq_flags); syscon1 = UDC_SYSCON1_REG; if (is_selfpowered) syscon1 |= UDC_SELF_PWR; else syscon1 &= ~UDC_SELF_PWR; UDC_SYSCON1_REG = syscon1; spin_unlock_irqrestore(&udc->lock, irq_flags); */ return 0; } void reset_ep(void) { #if 1 wmt_disable_fiq(); fiq_using = 0; pDevReg->Bulk1EpControl = EP_DMALIGHTRESET; while (pDevReg->Bulk1EpControl & EP_DMALIGHTRESET) ; pDevReg->Bulk2EpControl = EP_DMALIGHTRESET; while (pDevReg->Bulk2EpControl & EP_DMALIGHTRESET) ; pDevReg->Bulk3EpControl = EP_DMALIGHTRESET; while (pDevReg->Bulk3EpControl & EP_DMALIGHTRESET) ; #else pDevReg->Bulk1EpControl = 0; /* stop the bulk DMA*/ while (pDevReg->Bulk1EpControl & EP_ACTIVE) /* wait the DMA stopped*/ ; pDevReg->Bulk2EpControl = 0; /* stop the bulk DMA*/ while (pDevReg->Bulk2EpControl & EP_ACTIVE) /* wait the DMA stopped*/ ; pDevReg->Bulk3EpControl = 0; /* stop the bulk DMA*/ while (pDevReg->Bulk3EpControl & EP_ACTIVE) /* wait the DMA stopped*/ ; #endif pDevReg->Bulk1DesStatus = 0x00; pDevReg->Bulk2DesStatus = 0x00; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk1DesTbytes0 = 0; pDevReg->Bulk1DesTbytes1 = 0; pDevReg->Bulk1DesTbytes2 = 0; pDevReg->Bulk2DesTbytes0 = 0; pDevReg->Bulk2DesTbytes1 = 0; pDevReg->Bulk2DesTbytes2 = 0; pDevReg->Bulk3DesTbytes0 = 0; pDevReg->Bulk3DesTbytes1 = 0; pDevReg->Bulk3DesTbytes2 = 0; /* enable DMA and run the control endpoint*/ wmb(); pDevReg->ControlEpControl = EP_RUN + EP_ENABLEDMA; #if 0 /* enable DMA and run the bulk endpoint*/ pDevReg->Bulk1EpControl = EP_RUN + EP_ENABLEDMA; pDevReg->Bulk2EpControl = EP_RUN + EP_ENABLEDMA; #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpControl = EP_RUN + EP_ENABLEDMA; #else pDevReg->InterruptEpControl = EP_RUN + EP_ENABLEDMA; #endif #endif /* enable DMA and run the interrupt endpoint*/ /* UsbControlRegister.InterruptEpControl = EP_RUN+EP_ENABLEDMA;*/ /* run the USB controller*/ pDevReg->MiscControl3 = 0x3d; wmb(); pDevReg->PortControl |= PORTCTRL_SELFPOWER;/* Device port control register - 22*/ pDevReg->CommandStatus = USBREG_RUNCONTROLLER; wmb(); ControlState = CONTROLSTATE_SETUP; USBState = USBSTATE_DEFAULT; TestMode = 0; /*status = wmt_udc_setup(odev, xceiv);*/ wmt_ep_setup_csr("ep0", 0, USB_ENDPOINT_XFER_CONTROL, 64); #if 1 wmt_ep_setup_csr("ep1in-bulk", (USB_DIR_IN | 1), USB_ENDPOINT_XFER_BULK, 64); wmt_ep_setup_csr("ep2out-bulk", (USB_DIR_OUT | 2), USB_ENDPOINT_XFER_BULK, 64); #if 0 #ifdef USE_BULK3_TO_INTERRUPT wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 28); #else wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 8); #endif #endif #endif } void reset_udc(void) { /* if (!((*(volatile unsigned int *)(PM_CTRL_BASE_ADDR + 0x254))&0x00000080))*/ /* *(volatile unsigned int *)(PM_CTRL_BASE_ADDR + 0x254) |= 0x00000080;*/ /*DPM needed*/ pDevReg->CommandStatus |= USBREG_RESETCONTROLLER; wmb(); if ((*(volatile unsigned char *)(USB_IP_BASE + 0x249))&0x04) { *(volatile unsigned char*)(USB_IP_BASE + 0x249)&= ~0x04; mdelay(1); } pUSBMiscControlRegister5 = (unsigned char *)(USB_UDC_REG_BASE + 0x1A0); *pUSBMiscControlRegister5 = 0x01;/*USB in normal operation*/ /* reset Bulk descriptor control*/ wmb(); f_ep3_used = 0; reset_ep(); pDevReg->SelfPowerConnect |= 0x10;//Neil wmb(); /* enable all interrupt*/ #ifdef FULL_SPEED_ONLY pDevReg->IntEnable = (INTENABLE_ALL | INTENABLE_FULLSPEEDONLY) ;/*0x70*/ #else pDevReg->IntEnable = INTENABLE_ALL;/*0x70*/ #endif wmb(); /* set IOC on the Setup decscriptor to accept the Setup request*/ pDevReg->ControlDesControl = CTRLXFER_IOC; /*Neil_080731*/ /* pullup_disable here and enable in /arch/arm/kernel/apm.c:395 apm_ioctl() to patch issue signal fail when resume when recive*/ /* set_configuration time out.*/ /* pullup_enable(udc);//usb_gadget_probe_driver()*/ wmb(); wmt_pdma_reset(); // pullup_enable(udc); // pDevReg->FunctionPatchEn |= 0x20; /* HW attach process evaluation enable bit*/ /* pullup_disable(udc);*/ /*Neil_080731*/ } /* static int can_pullup(struct vt8500_udc *udc) { return udc->driver && udc->softconnect && udc->vbus_active; } */ static void pullup_disable(struct vt8500_udc *udc) { INFO("pullup_disable()\n"); /*Hold port control's FSM from enter device mode.*/ //pDevReg->PhyMisc &= 0x0F; //pDevReg->PhyMisc |= 0x10; pDevReg->FunctionPatchEn &= (~0x20); /* HW attach process evaluation enable bit*/ wmb(); gadget_connect=0; f_ep3_used = 0; reset_ep(); wmt_pdma_reset(); } /*static void pullup_disable()*/ /* * Called by whatever detects VBUS sessions: external transceiver * driver, or maybe GPIO0 VBUS IRQ. May request 48 MHz clock. */ static int wmt_vbus_session(struct usb_gadget *gadget, int is_active) { DBG("wmt_vbus_session()\n"); return 0; } static int wmt_vbus_draw(struct usb_gadget *gadget, unsigned mA) { DBG("wmt_vbus_draw()\n"); return -EOPNOTSUPP; } static int wmt_pullup(struct usb_gadget *gadget, int is_on) { struct vt8500_udc *udc; // unsigned long flags; DBG("wmt_pullup()\n"); udc = container_of(gadget, struct vt8500_udc, gadget); down(&wmt_udc_sem); spin_lock_irqsave(&udc->lock, irq_flags); udc->softconnect = (is_on != 0); // if (can_pullup(udc)) if (udc->softconnect) pullup_enable(udc); else { pullup_disable(udc); //run_script(action_off_line); } spin_unlock_irqrestore(&udc->lock, irq_flags); up(&wmt_udc_sem); return 0; } void get_udc_sem (void) { down(&wmt_udc_sem); } void release_udc_sem (void) { up(&wmt_udc_sem); } static int wmt_udc_start(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *)); static int wmt_udc_stop(struct usb_gadget_driver *driver); static struct usb_gadget_ops wmt_gadget_ops = { .get_frame = wmt_get_frame, .wakeup = wmt_wakeup, .set_selfpowered = wmt_set_selfpowered, .vbus_session = wmt_vbus_session, .vbus_draw = wmt_vbus_draw, .pullup = wmt_pullup, .start = wmt_udc_start, .stop = wmt_udc_stop, }; /* dequeue ALL requests; caller holds udc->lock */ static void nuke(struct vt8500_ep *ep, int status) { struct vt8500_req *req; DBG("nuke()\n"); ep->stopped = 1; while (!list_empty(&ep->queue)) { req = list_entry(ep->queue.next, struct vt8500_req, queue); done(ep, req, status); } } /*void nuke()*/ /* caller holds udc->lock */ static void udc_quiesce(struct vt8500_udc *udc) { struct vt8500_ep *ep; DBG("udc_quiesce()\n"); udc->gadget.speed = USB_SPEED_UNKNOWN; nuke(&udc->ep[0], -ESHUTDOWN); list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) nuke(ep, -ESHUTDOWN); } /*void udc_quiesce()*/ /* static void update_otg(struct vt8500_udc *udc) { u16 devstat; if (!udc->gadget.is_otg) return; if (OTG_CTRL_REG & OTG_ID) devstat = UDC_DEVSTAT_REG; else devstat = 0; udc->gadget.b_hnp_enable = !!(devstat & UDC_B_HNP_ENABLE); udc->gadget.a_hnp_support = !!(devstat & UDC_A_HNP_SUPPORT); udc->gadget.a_alt_hnp_support = !!(devstat & UDC_A_ALT_HNP_SUPPORT); // Enable HNP early, avoiding races on suspend irq path. // ASSUMES OTG state machine B_BUS_REQ input is true. // if (udc->gadget.b_hnp_enable) OTG_CTRL_REG = (OTG_CTRL_REG | OTG_B_HNPEN | OTG_B_BUSREQ) & ~OTG_PULLUP; }//static void update_otg() */ /* define the prepare result codes*/ #define RESPOK 0 #define RESPFAIL 1 u16 Control_Length; /* the length of transfer for current control transfer*/ u16 Configure_Length; /*UDC_IS_SETUP_INT*/ static void udc_control_prepare_data_resp(void)/*(struct vt8500_udc *udc, u32 udc_irq_src)*/ { struct vt8500_ep *ep0 = &udc->ep[0]; struct vt8500_req *req = 0; /*UCHAR Result = RESPFAIL;*/ /*unsigned char CurXferLength = 0;*/ /*unsigned char Control_Length = 0;*/ int i; u8 test_mode_enable = 0; Configure_Length = 0; /*ep0->irqs++;*/ DBG("ep0_irq()\n"); ep0->toggle_bit = 1; if (!list_empty(&ep0->queue)) req = container_of(ep0->queue.next, struct vt8500_req, queue); /* SETUP starts all control transfers*/ { union u { u8 bytes[8]; struct usb_ctrlrequest r; } u; int status = -EINVAL; struct vt8500_ep *ep = &udc->ep[0]; int ep0_status_phase_0_byte = 0; nuke(ep0, 0); /* read the (latest) SETUP message*/ for (i = 0; i <= 7; i++) u.bytes[i] = pSetupCommandBuf[i]; le32_to_cpus(&u.r.wValue); le32_to_cpus(&u.r.wIndex); le32_to_cpus(&u.r.wLength); /* Delegate almost all control requests to the gadget driver,*/ /* except for a handful of ch9 status/feature requests that*/ /* hardware doesn't autodecode _and_ the gadget API hides.*/ /**/ udc->ep0_in = (u.r.bRequestType & USB_DIR_IN) != 0; udc->ep0_set_config = 0; udc->ep0_pending = 1; udc->ep0_in_status = 0; ep0->stopped = 0; ep0->ackwait = 0; if ((u.r.bRequestType & USB_RECIP_OTHER) == USB_RECIP_OTHER) {/*USB_RECIP_OTHER(0x03)*/ status = 0; /*INFO("ep0_irq() setup command[0]=(0x%08X)\n",u.dword[0]);*/ /*INFO("ep0_irq() setup command[1]=(0x%08X)\n",u.dword[1]);*/ /*INFO("ep0_irq() address(%08X)", udc_reg->AddressControl);*/ goto delegate; } switch (u.r.bRequest) { case USB_REQ_SET_CONFIGURATION: /* udc needs to know when ep != 0 is valid*/ /*SETUP 00.09 v0001 i0000 l0000*/ if (u.r.bRequestType != USB_RECIP_DEVICE)/*USB_RECIP_DEVICE(0x00)*/ goto delegate; if (u.r.wLength != 0) goto do_stall; udc->ep0_set_config = 1; udc->ep0_reset_config = (u.r.wValue == 0); VDBG("set config %d\n", u.r.wValue); if (u.r.wValue == 0) USBState = USBSTATE_ADDRESS; else USBState = USBSTATE_CONFIGED; /* update udc NOW since gadget driver may start*/ /* queueing requests immediately; clear config*/ /* later if it fails the request.*/ /**/ udc->ep[0].toggle_bit = 0; udc->ep[1].toggle_bit = 0; udc->ep[2].toggle_bit = 0; udc->ep[3].toggle_bit = 0; udc->ep[4].toggle_bit = 0; udc->ep[5].toggle_bit = 0;//gri udc->ep[6].toggle_bit = 0;//gri status = 0; goto delegate; /* Giga Hsu : 2007.6.6 This would cause set interface status 0 return to fast and cause bulk endpoint in out error*/ case USB_REQ_SET_INTERFACE: VDBG("set interface %d\n", u.r.wValue); status = 0; udc->ep[0].toggle_bit = 0; udc->ep[1].toggle_bit = 0; udc->ep[2].toggle_bit = 0; udc->ep[3].toggle_bit = 0; udc->ep[4].toggle_bit = 0; udc->ep[5].toggle_bit = 0;//gri udc->ep[6].toggle_bit = 0;//gri goto delegate; /*break;*/ case USB_REQ_CLEAR_FEATURE: /* clear endpoint halt*/ if (u.r.bRequestType != USB_RECIP_ENDPOINT) goto delegate; if (u.r.wValue != USB_ENDPOINT_HALT || u.r.wLength != 0) goto do_stall; ep = &udc->ep[u.r.wIndex & 0xf]; if (ep != ep0) { if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC || !ep->desc) goto do_stall; if (udc->file_storage_set_halt == 0) { switch ((ep->bEndpointAddress & 0x7F)) { case 0:/*Control In/Out*/ pDevReg->ControlEpControl &= 0xF7; break; case 1:/*Bulk In*/ pDevReg->Bulk1EpControl &= 0xF7; #ifdef MSC_COMPLIANCE_TEST udc_bulk_dma_dump_register(); udc_device_dump_register(); #endif if (ep->stall_more_processing == 1) { u32 dma_ccr = 0; ep->stall_more_processing = 0; wmt_pdma0_reset(); wmt_udc_pdma_des_prepare(ep->temp_dcmd, ep->temp_bulk_dma_addr, DESCRIPTOT_TYPE_LONG, TRANS_IN, 1); pDevReg->Bulk1DesStatus = 0x00; pDevReg->Bulk1DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk1DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk1DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ if (ep->ep_stall_toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk1DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk1DesTbytes2 &= 0xBF; } pDevReg->Bulk1DesStatus = (BULKXFER_IOC | BULKXFER_IN); /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ dma_ccr = 0; dma_ccr = DMA_RUN; wmb(); pUdcDmaReg->DMA_Context_Control0 = dma_ccr; //neil wmb(); pDevReg->Bulk1DesStatus |= BULKXFER_ACTIVE; } break; case 2:/*Bulk Out*/ pDevReg->Bulk2EpControl &= 0xF7; if (ep->stall_more_processing == 1) { u32 dma_ccr = 0; ep->stall_more_processing = 0; wmt_pdma1_reset(); // wmt_pdma_reset(); wmt_udc_pdma_des_prepare(ep->temp_dcmd, ep->temp_bulk_dma_addr, DESCRIPTOT_TYPE_LONG, TRANS_OUT, 1); /* DMA Global Controller Reg*/ /* DMA Controller Enable +*/ /* DMA Global Interrupt Enable(if any TC, error, or abort status in any channels occurs)*/ pDevReg->Bulk2DesStatus = 0x00; pDevReg->Bulk2DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk2DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk2DesTbytes0 = ep->temp_dcmd & 0xFF; if (ep->ep_stall_toggle_bit) pDevReg->Bulk2DesTbytes2 |= BULKXFER_DATA1; else pDevReg->Bulk2DesTbytes2 &= 0x3F; pDevReg->Bulk2DesStatus = BULKXFER_IOC; /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ /*udc_bulk_dma_dump_register();*/ dma_ccr = 0; dma_ccr = DMA_RUN; dma_ccr |= DMA_TRANS_OUT_DIR; wmb(); pUdcDmaReg->DMA_Context_Control1 = dma_ccr; wmb(); pDevReg->Bulk2DesStatus |= BULKXFER_ACTIVE; } break; case 3:/*Interrupt In*/ #ifdef USE_BULK3_TO_INTERRUPT /*Bulk In*/ pDevReg->Bulk3EpControl &= 0xF7; #ifdef MSC_COMPLIANCE_TEST udc_bulk_dma_dump_register(); udc_device_dump_register(); #endif if (ep->stall_more_processing == 1) { u32 dma_ccr = 0; ep->stall_more_processing = 0; wmt_pdma2_reset(); wmt_udc_pdma_des_prepare(ep->temp_dcmd, ep->temp_bulk_dma_addr, DESCRIPTOT_TYPE_LONG, TRANS_IN, 0); pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk3DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk3DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ if (ep->ep_stall_toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk3DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk3DesTbytes2 &= 0xBF; } pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ dma_ccr = 0; dma_ccr = DMA_RUN; wmb(); pUdcDmaReg->DMA_Context_Control2 = dma_ccr; //neil wmb(); pDevReg->Bulk3DesStatus |= BULKXFER_ACTIVE; } #else /*Interrupt In*/ pDevReg->InterruptEpControl &= 0xF7; #endif break; case 4:/*Iso In*/ pDevReg->Bulk3EpControl &= 0xF7; #ifdef MSC_COMPLIANCE_TEST udc_bulk_dma_dump_register(); udc_device_dump_register(); #endif if (ep->stall_more_processing == 1) { u32 dma_ccr = 0; ep->stall_more_processing = 0; wmt_pdma2_reset(); wmt_udc_pdma_des_prepare(ep->temp_dcmd, ep->temp_bulk_dma_addr, DESCRIPTOT_TYPE_LONG, TRANS_IN, 0); pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes2 |= (ep->temp_dcmd >> 16) & 0x3; pDevReg->Bulk3DesTbytes1 = (ep->temp_dcmd >> 8) & 0xFF; pDevReg->Bulk3DesTbytes0 = ep->temp_dcmd & 0xFF; /* set endpoint data toggle*/ if (ep->ep_stall_toggle_bit) { /* BULKXFER_DATA1;*/ pDevReg->Bulk3DesTbytes2 |= 0x40; } else { /*(~BULKXFER_DATA1);*/ pDevReg->Bulk3DesTbytes2 &= 0xBF; } pDevReg->Bulk3DesStatus = (BULKXFER_IOC | BULKXFER_IN); /* DMA Channel Control Reg*/ /* Software Request + Channel Enable*/ dma_ccr = 0; dma_ccr = DMA_RUN; wmb(); pUdcDmaReg->DMA_Context_Control2 = dma_ccr; //neil wmb(); pDevReg->Bulk3DesStatus |= BULKXFER_ACTIVE; } break; } ep->stall = 0; ep->stopped = 0; /**ep->reg_irp_descriptor = ep->temp_irp_descriptor;*/ } } /*if (ep != ep0)*/ ep0_status_phase_0_byte = 1; VDBG("%s halt cleared by host\n", ep->name); /*goto ep0out_status_stage;*/ status = 0; udc->ep0_pending = 0; /*break;*/ goto delegate; case USB_REQ_SET_FEATURE: /* set endpoint halt*/ if ((u.r.wValue == USB_DEVICE_TEST_MODE)) {/*(USBState == USBSTATE_DEFAULT) &&*/ TestMode = (UCHAR)(u.r.wIndex >> 8); test_mode_enable = 1; INFO("USB_REQ_SET_FEATURE - TestMode (0x%02X)\n", TestMode); /*ControlState = CONTROLSTATE_STATUS;*/ ep0_status_phase_0_byte = 1; status = 0; break; } if (u.r.bRequestType != USB_RECIP_ENDPOINT) goto delegate; if (u.r.wValue != USB_ENDPOINT_HALT || u.r.wLength != 0) goto do_stall; ep = &udc->ep[u.r.wIndex & 0xf]; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC || ep == ep0 || !ep->desc) goto do_stall; wmb(); switch ((ep->bEndpointAddress & 0x7F)) { case 0:/*Control In/Out*/ pDevReg->ControlEpControl |= EP_STALL; break; case 1:/*Bulk In*/ pDevReg->Bulk1EpControl |= EP_STALL; break; case 2:/*Bulk Out*/ pDevReg->Bulk2EpControl |= EP_STALL; break; case 3: #ifdef USE_BULK3_TO_INTERRUPT /*Bulk Out*/ pDevReg->Bulk3EpControl |= EP_STALL; #else /*Interrupt In*/ pDevReg->InterruptEpControl |= EP_STALL; #endif break; case 4: /*Bulk Out*/ pDevReg->Bulk3EpControl |= EP_STALL; break; } wmb(); ep->stall = 1; ep->stopped = 1; ep0_status_phase_0_byte = 1; /*use_ep(ep, 0);*/ /* can't halt if fifo isn't empty...*/ /*UDC_CTRL_REG = UDC_CLR_EP;*/ /*UDC_CTRL_REG = UDC_SET_HALT;*/ VDBG("%s halted by host\n", ep->name); /*ep0out_status_stage:*/ status = 0; udc->ep0_pending = 0; /*break;*/ goto delegate; case USB_REQ_GET_STATUS: /* return interface status. if we were pedantic,*/ /* we'd detect non-existent interfaces, and stall.*/ /**/ if (u.r.bRequestType == (USB_DIR_IN|USB_RECIP_ENDPOINT)) { ep = &udc->ep[u.r.wIndex & 0xf]; if (ep->stall == 1) { udc->ep0_in_status = 0x01; /*GgiaHsu-B 2007.08.10 : patch HW Bug : MSC Compliance Test : Error Recovery Items.*/ ep = &udc->ep[3]; if ((udc->file_storage_set_halt == 1) && (ep->stall == 1)) ep->stall = 1; /*GgiaHsu-E 2007.08.10 : --------------------------------------------*/ ep = &udc->ep[0]; ep->stall = 0; } else udc->ep0_in_status = 0x00; VDBG("GET_STATUS, interface wIndex(0x%02X) ep0_in_status(0x%04X)\n" , u.r.wIndex, udc->ep0_in_status); } else udc->ep0_in_status = 0x00; /* return two zero bytes*/ status = 0; /* next, status stage*/ goto delegate; break; case USB_REQ_SET_ADDRESS: if (u.r.bRequestType == USB_RECIP_DEVICE) { /*USB_RECIP_DEVICE(0x00)*/ if (USBState == USBSTATE_DEFAULT) { if (u.r.wValue != 0) USBState = USBSTATE_ADDRESS; } else if (USBState == USBSTATE_ADDRESS) { if (u.r.wValue == 0) USBState = USBSTATE_DEFAULT; } pDevReg->DeviceAddr |= (DEVADDR_ADDRCHANGE | u.r.wValue); VDBG("USB_REQ_SET_ADDRESS 0x%03d\n", u.r.wValue); ControlState = CONTROLSTATE_STATUS; ep0_status_phase_0_byte = 1; status = 0; } break; case USB_BULK_RESET_REQUEST: VDBG("USB_BULK_RESET_REQUEST\n"); udc->file_storage_set_halt = 0; udc->ep[0].toggle_bit = 0; udc->ep[1].toggle_bit = 0; udc->ep[2].toggle_bit = 0; udc->ep[3].toggle_bit = 0; udc->ep[4].toggle_bit = 0; udc->ep[5].toggle_bit = 0;//gri udc->ep[6].toggle_bit = 0;//gri status = 0; goto delegate; /*break;*/ default: delegate: VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", u.r.bRequestType, u.r.bRequest, u.r.wValue, u.r.wIndex, u.r.wLength); /* // The gadget driver may return an error here, // causing an immediate protocol stall. // // Else it must issue a response, either queueing a // response buffer for the DATA stage, or halting ep0 // (causing a protocol stall, not a real halt). A // zero length buffer means no DATA stage. // // It's fine to issue that response after the setup() // call returns, and this IRQ was handled. // */ udc->ep0_setup = 1; spin_unlock_irqrestore(&udc->lock, irq_flags); /*usb gadget driver prepare setup data phase(control in)*/ status = udc->driver->setup(&udc->gadget, &u.r); /*usb_gadget_driver->setup()*/ spin_lock_irqsave(&udc->lock, irq_flags); udc->ep0_setup = 0; } /*switch (u.r.bRequest)*/ if (ep0_status_phase_0_byte == 1) {/* && (udc->ep[0].stall==0))*/ udc->ep0_status_0_byte = 1; if (test_mode_enable == 1) ep0_status(udc); } if (status < 0) { do_stall: /* ep = &udc->ep[0];*/ /**ep->reg_control_status |= UDC_EP0_STALL;*/ /* fail in the command parsing*/ pDevReg->ControlEpControl |= EP_STALL; /* stall the pipe*/ wmb(); ControlState = CONTROLSTATE_SETUP; /* go back to setup state*/ ep->stall = 1; DBG("Setup Command STALL : req %02x.%02x protocol STALL; stat %d\n", u.r.bRequestType, u.r.bRequest, status); udc->ep0_pending = 0; } /*if (status < 0)*/ } /*if (udc_irq_src & UDC_IS_SETUP_INT)*/ } /*udc_control_prepare_data_resp()*/ #define OTG_FLAGS (UDC_B_HNP_ENABLE|UDC_A_HNP_SUPPORT|UDC_A_ALT_HNP_SUPPORT) static void devstate_irq(struct vt8500_udc *udc, u32 port0_status) { udc->usb_connect = 0; if (pDevReg->IntEnable & INTENABLE_DEVICERESET) { /*vt3357 hw issue : clear all device register.*/ /*payload & address needs re-set again...*/ pDevReg->IntEnable |= INTENABLE_SUSPENDDETECT; VDBG("devstate_irq() - Global Reset...\n"); //printk("[devstate_irq]0xd8009834 = 0x%8.8x\n",*(volatile unsigned int *)(USB_IP_BASE+0x2034)); if (udc->driver) { udc->gadget.speed = USB_SPEED_UNKNOWN; // ppudc = udc; // run_script(action_off_line); // udc->driver->disconnect(&udc->gadget); } udc->ep0_set_config = 0; pDevReg->Bulk1DesStatus = 0; udc->ep[0].toggle_bit = 0; udc->ep[1].toggle_bit = 0; udc->ep[2].toggle_bit = 0; udc->ep[3].toggle_bit = 0; udc->ep[4].toggle_bit = 0; udc->ep[5].toggle_bit = 0;//gri udc->ep[6].toggle_bit = 0;//gri udc->ep[0].rndis = 0; udc->ep[1].rndis = 0; udc->ep[2].rndis = 0; udc->ep[3].rndis = 0; udc->ep[4].rndis = 0; udc->ep[5].rndis = 0;//gri udc->ep[6].rndis = 0;//gri udc->file_storage_set_halt = 0; udc->bulk_out_dma_write_error = 0; udc->gadget.speed = USB_SPEED_UNKNOWN; wmt_pdma_reset(); gadget_connect=0; /*vt8500_usb_device_reg_dump();*/ } /*if (pDevReg->IntEnable & INTENABLE_DEVICERESET)*/ if (pDevReg->IntEnable & INTENABLE_SUSPENDDETECT) { VDBG("devstate_irq() - Global Suspend...\n"); pDevReg->IntEnable |= INTENABLE_SUSPENDDETECT; } /*if (pDevReg->IntEnable & INTENABLE_SUSPENDDETECT)*/ if (pDevReg->IntEnable & INTENABLE_RESUMEDETECT) { pDevReg->IntEnable |= INTENABLE_RESUMEDETECT; VDBG("devstate_irq() - Global Resume...\n"); } /*if (pDevReg->IntEnable & INTENABLE_RESUMEDETECT)*/ /*#ifdef UDC_A1_SELF_POWER_ENABLE*/ /* USB Bus Connection Change*/ /* clear connection change event*/ if (pDevReg->PortControl & PORTCTRL_SELFPOWER)/* Device port control register - 22)*/ if (pDevReg->PortControl & PORTCTRL_CONNECTCHANGE)/* Device port control register - 22)*/ pDevReg->PortControl |= PORTCTRL_CONNECTCHANGE;/* 0x02 // connection change bit*/ /*#endif*/ if (pDevReg->PortControl & PORTCTRL_FULLSPEEDMODE) { udc->gadget.speed = USB_SPEED_FULL; udc->usb_connect = 1; /*2007-8.27 GigaHsu : enable float, reset, suspend and resume IE*/ /*after host controller connected.*/ VDBG("devstate_irq() - full speed host connect...\n"); } /*if(pDevReg->PortControl & PORTCTRL_FULLSPEEDMODE)*/ if (pDevReg->PortControl & PORTCTRL_HIGHSPEEDMODE) { udc->gadget.speed = USB_SPEED_HIGH; udc->usb_connect = 1; /*2007-8.27 GigaHsu : enable float, reset, suspend and resume IE*/ /*after host controller connected.*/ VDBG("devstate_irq() - high speed host connect...\n"); } /*if(pDevReg->PortControl & PORTCTRL_HIGHSPEEDMODE)*/ } /*static void devstate_irq()*/ void USB_ControlXferComplete(void) { struct vt8500_ep *ep; struct vt8500_req *req; ep = &udc->ep[0]; /* when ever a setup received, the Control state will reset*/ /* check for the valid bit of the contol descriptor*/ /*DBG("USB_ControlXferComplete()\n");*/ if (pDevReg->ControlDesControl & CTRLXFER_CMDVALID) { ep->toggle_bit = 1; if (udc->usb_connect == 0) { if (pDevReg->PortControl & PORTCTRL_FULLSPEEDMODE) { udc->gadget.speed = USB_SPEED_FULL; udc->usb_connect = 1; udc->gadget.max_speed = USB_SPEED_HIGH; /*2007-8.27 GigaHsu : enable float, reset, suspend and resume IE*/ /*after host controller connected.*/ //wmt_udc_csr(udc); VDBG("devstate_irq() - full speed host connect...\n"); USBState = USBSTATE_DEFAULT; } /*if(pDevReg->PortControl & PORTCTRL_FULLSPEEDMODE)*/ if (pDevReg->PortControl & PORTCTRL_HIGHSPEEDMODE) { udc->gadget.speed = USB_SPEED_HIGH; udc->usb_connect = 1; udc->gadget.max_speed = USB_SPEED_HIGH; /*2007-8.27 GigaHsu : enable float, reset, suspend and resume IE*/ /*after host controller connected.*/ //wmt_udc_csr(udc); VDBG("devstate_irq() - high speed host connect...\n"); USBState = USBSTATE_DEFAULT; } /*if(pDevReg->PortControl & PORTCTRL_HIGHSPEEDMODE)*/ } /* HP11_Begin*/ /* clear the command valid bit*/ /* pDevReg->ControlDesControl |= CTRLXFER_CMDVALID;*/ /* always clear control stall when SETUP received*/ pDevReg->ControlEpControl &= 0x17; /* clear the stall*/ wmb(); ControlState = CONTROLSTATE_DATA; udc_control_prepare_data_resp(); /*processing SETUP command ...*/ pDevReg->ControlDesControl &= 0xEF;/*(~CTRLXFER_CMDVALID);*/ wmb(); /*HP11_End*/ return; } if (udc->ep0_in) { /* IN dma: tx to host*/ if (!list_empty(&ep->queue)) { /* >64 bytes for prepare DATA*/ req = container_of(ep->queue.next, struct vt8500_req, queue); VDBG("dma_irq : finish_in_dma() EP0 %s\n", ep ? ep->ep.name : NULL); finish_in_dma(ep, req, 0); } while (pDevReg->ControlEpControl & EP_COMPLETEINT) /* clear the event*/ ; if (!list_empty(&ep->queue)) { /* >64 bytes for prepare DATA*/ req = container_of(ep->queue.next, struct vt8500_req, queue); VDBG("dma_irq : next_in_dma() EP0 %s\n", ep ? ep->ep.name : NULL); next_in_dma(ep, req); } } else {/*ep0 out*/ /* OUT dma: rx from host*/ if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct vt8500_req, queue); finish_out_dma(ep, req, 0); } while (pDevReg->ControlEpControl & EP_COMPLETEINT) /* clear the event*/ ; if (!list_empty(&ep->queue)) { /* >64 bytes for prepare DATA*/ req = container_of(ep->queue.next, struct vt8500_req, queue); next_out_dma(ep, req); } } } /*void USB_ControlXferComplete(void)*/ static irqreturn_t wmt_udc_dma_irq(int irq, void *_udc)//, struct pt_regs *r) { irqreturn_t status = IRQ_NONE; u32 bulk_dma_csr; bulk_dma_csr = pUdcDmaReg->DMA_ISR; /*printk("[udc_dma_isr]dma int_sts = 0x%8.8x\n",pUdcDmaReg->DMA_ISR);*/ if (bulk_dma_csr & DMA_INTERRUPT_STATUS0) { /* printk("[udc_dma_isr]channel0 event = 0x%8.8x\n",pUdcDmaReg->DMA_Context_Control0);*/ pUdcDmaReg->DMA_ISR = DMA_INTERRUPT_STATUS0; status = IRQ_HANDLED; } if (bulk_dma_csr & DMA_INTERRUPT_STATUS1) { /* printk("[udc_dma_isr]channel1 event = 0x%8.8x\n",pUdcDmaReg->DMA_Context_Control1);*/ pUdcDmaReg->DMA_ISR = DMA_INTERRUPT_STATUS1; status = IRQ_HANDLED; } if (bulk_dma_csr & DMA_INTERRUPT_STATUS2) { /* printk("[udc_dma_isr]channel2 event = 0x%8.8x\n",pUdcDmaReg->DMA_Context_Control2);*/ pUdcDmaReg->DMA_ISR = DMA_INTERRUPT_STATUS2; //printk("iso dma hit\n"); dma_irq(0x84); status = IRQ_HANDLED; } return status; } static irqreturn_t wmt_udc_irq(int irq, void *_udc)//, struct pt_regs *r) { struct vt8500_udc *udc = _udc; u32 udc_irq_src; irqreturn_t status = IRQ_NONE; // unsigned long flags; #ifdef OTGIP u32 global_irq_src; #endif /*u32 i;*/ spin_lock_irqsave(&udc->lock, irq_flags); DBG("wmt_udc_irq()\n"); #ifdef OTGIP /*Global Interrupt Status*/ global_irq_src = pGlobalReg->UHDC_Interrupt_Status; if (global_irq_src & UHDC_INT_UDC) {/*UDC Core + UDC DMA1 + UDC DMA2 */ if (global_irq_src & UHDC_INT_UDC_CORE) {/*UDC Core*/ #endif /*connection interrupt*/ if (pDevReg->SelfPowerConnect & 0x02) { //struct usb_gadget_driver *driver = udc->driver; if (pDevReg->SelfPowerConnect & 0x01) //connect { // wmt_pdma_reset(); reset_udc(); //pullup_enable(udc); } else {//disconnct // spin_unlock_irqrestore(&udc->lock, irq_flags); // if (udc->driver) // udc->driver->disconnect(&udc->gadget); // ppudc = udc; printk(KERN_INFO "disconnect 1\n"); //gri run_script(action_off_line); gadget_connect=0; // pullup_disable(udc); } status = IRQ_HANDLED; pDevReg->SelfPowerConnect |= 0x02; } wmb(); /* Device Global Interrupt Pending Status*/ udc_irq_src = pDevReg->CommandStatus; /* Device state change (usb ch9 stuff)*/ if (udc_irq_src & USBREG_BUSACTINT) {/* the bus activity interrupt occured*/ /*caused by Port 0 Statsu Change*/ devstate_irq(_udc, udc_irq_src); status = IRQ_HANDLED; pDevReg->CommandStatus |= USBREG_BUSACTINT; wmb(); } if (udc_irq_src & USBREG_BABBLEINT) {/* the Babble interrupt ocuured*/ /* check for Control endpoint for BABBLE error*/ if (pDevReg->ControlEpControl & EP_BABBLE) { /* the Control endpoint is encounted the babble error*/ /* stall the endpoint and clear the babble condition*/ pDevReg->ControlEpControl |= (EP_BABBLE + EP_STALL); INFO("vt8430_udc_irq() - EP0 Babble Detect!\n"); udc->ep[0].stopped = 1; udc->ep[0].stall = 1; } if (pDevReg->Bulk1EpControl & EP_BABBLE) { /* the Bulk endpoint is encounted the babble error*/ /* stall the endpoint and clear the babble condition*/ pDevReg->Bulk1EpControl |= (EP_BABBLE + EP_STALL); INFO("vt8430_udc_irq() - EP1 Babble Detect!\n"); udc->ep[1].stopped = 1; udc->ep[1].stall = 1; } if (pDevReg->Bulk2EpControl & EP_BABBLE) { /* the Bulk endpoint is encounted the babble error*/ /* stall the endpoint and clear the babble condition*/ pDevReg->Bulk2EpControl |= (EP_BABBLE + EP_STALL); INFO("vt8430_udc_irq() - EP2 Babble Detect!\n"); udc->ep[2].stopped = 1; udc->ep[2].stall = 1; } if (pDevReg->Bulk3EpControl & EP_BABBLE) { /* the Bulk endpoint is encounted the babble error*/ /* stall the endpoint and clear the babble condition*/ pDevReg->Bulk3EpControl |= (EP_BABBLE + EP_STALL); INFO("vt8430_udc_irq() - EP3 Babble Detect!\n"); udc->ep[3].stopped = 1; udc->ep[3].stall = 1; } wmb(); status = IRQ_HANDLED; } if (udc_irq_src & USBREG_COMPLETEINT) {/* the complete inerrupt occured*/ if (pDevReg->ControlEpControl & EP_COMPLETEINT) { /* the control transfer complete event*/ pDevReg->ControlEpControl |= EP_COMPLETEINT; /* clear the event*/ wmb(); USB_ControlXferComplete(); #if 0 gadget_connect=1; #endif } if (pDevReg->Bulk1EpControl & EP_COMPLETEINT) { /* the bulk transfer complete event*/ pDevReg->Bulk1EpControl |= EP_COMPLETEINT; wmb(); /*DBG("USB_Bulk 1 DMA()\n");*/ dma_irq(0x81); #if 1 gadget_connect=1; #endif } if (pDevReg->Bulk2EpControl & EP_COMPLETEINT) { /* the bulk transfer complete event*/ pDevReg->Bulk2EpControl |= EP_COMPLETEINT; wmb(); /*DBG("USB_Bulk 2 DMA()\n");*/ dma_irq(2); #if 1 gadget_connect=1; #endif } #ifdef USE_BULK3_TO_INTERRUPT if (pDevReg->Bulk3EpControl & EP_COMPLETEINT) { /* the bulk transfer complete event*/ pDevReg->Bulk3EpControl |= EP_COMPLETEINT; wmb(); /*DBG("USB_Bulk 3 DMA()\n");*/ dma_irq(0x83); #if 1 gadget_connect=1; #endif } #else if (pDevReg->InterruptEpControl & EP_COMPLETEINT) { /* the bulk transfer complete event*/ pDevReg->InterruptEpControl |= EP_COMPLETEINT; /*DBG("USB_INT 3 DMA()\n");*/ if (f_ep3_used == 3) dma_irq(0x83); #if 1 gadget_connect=1; #endif } #endif status = IRQ_HANDLED; } if (udc->ep0_status_0_byte == 1)/* && (udc_ep[0].stall==0))*/ ep0_status(udc); if (ControlState == CONTROLSTATE_STATUS) { /* checking for test mode*/ if (TestMode != 0x00) { #if 0 pDevReg->CommandStatus &= 0x1F; wmb(); pDevReg->CommandStatus |= USBREG_RESETCONTROLLER; while (pDevReg->CommandStatus & USBREG_RESETCONTROLLER) ; /* HW attach process evaluation enable bit*/ #if 0 pDevReg->FunctionPatchEn |= 0x20; /* Device port control register - 22*/ pDevReg->PortControl |= PORTCTRL_SELFPOWER; wmb(); #else pullup_enable(udc); pDevReg->FunctionPatchEn |= 0x20; /* HW attach process evaluation enable bit*/ wmb(); //msleep(1000); #endif #endif wmb(); udelay(1000); /*GigaHsu 2008.1.26 : Don't set RUN bit while TestMode enable*/ /* setting the test mode*/ switch (TestMode) { case UDC_TEST_MODE_NOT_ENABLED:/*0*/ INFO("UDC_TEST_MODE_NOT_ENABLED (0x%02X)\n", TestMode); break; case UDC_TEST_J_STATE:/*1*/ pDevReg->CommandStatus = USBREG_TEST_J; INFO("UDC_TEST_J_STATE wIndex(0x%02X)\n", TestMode); break; case UDC_TEST_K_STATE:/*2*/ pDevReg->CommandStatus = USBREG_TEST_K; INFO("UDC_TEST_K_STATE wIndex(0x%02X)\n", TestMode); break; case UDC_TEST_SE0_NAK:/*3*/ pDevReg->CommandStatus = USBREG_SE0_NAK; INFO("UDC_TEST_SE0_NAK wIndex(0x%02X)\n", TestMode); break; case UDC_TEST_PACKET:/*4*/ pDevReg->CommandStatus = USBREG_TESTPACKET; INFO("UDC_TEST_PACKET wIndex(0x%02X)\n", TestMode); break; case UDC_TEST_FRORCE_ENABLE:/*5*/ pDevReg->CommandStatus = USBREG_FORCEENABLE; INFO("UDC_TEST_FRORCE_ENABLE wIndex(0x%02X)\n", TestMode); break; case UDC_TEST_EYE_PATTERN:/*6*/ pDevReg->CommandStatus = USBREG_TESTEYE; INFO("UDC_TEST_EYE_PATTERN wIndex(0x%02X)\n", TestMode); break; } /*switch(TestMode)*/ INFO("UDC - CommandStatus(0x%02X)\n", pDevReg->CommandStatus); /* stop the 8051*/ /*ChipTopRegister.Config |= CT_STOP8051;*/ } ControlState = CONTROLSTATE_SETUP; /* go back SETUP state*/ } #ifdef OTGIP } global_irq_src = pGlobalReg->UHDC_Interrupt_Status; if (global_irq_src & UHDC_INT_UDC_DMA1)/*UDC Bulk DMA 1*/ status = wmt_udc_dma_irq(UDC_IRQ_USB, udc);//, r); // if (global_irq_src & UHDC_INT_UDC_DMA2)/*UDC Bulk DMA 1*/ // wmt_udc_dma_irq(UDC_IRQ_USB, udc);//, r); // if (global_irq_src & UHDC_INT_UDC_DMA3)/*UDC Bulk DMA 1*/ // wmt_udc_dma_irq(UDC_IRQ_USB, udc);//, r); } #endif spin_unlock_irqrestore(&udc->lock, irq_flags); //printk("udc s =0x%x\n",pGlobalReg->UHDC_Interrupt_Status); return status; } /*wmt_udc_irq()*/ /* workaround for seemingly-lost IRQs for RX ACKs... */ #define PIO_OUT_TIMEOUT (jiffies + HZ/3) #ifdef DEBUG_UDC_ISR_TIMER static void wmt_udc_softirq(unsigned long _udc) { struct vt8500_udc *udc = (void *) _udc; /*unsigned long flags;*/ struct pt_regs r; INFO("wmt_udc_softirq()\n"); wmt_udc_irq(UDC_IRQ_USB, udc, &r); mod_timer(&udc->timer, PIO_OUT_TIMEOUT); } #endif static void __init wmt_ep_setup(char *name, u8 addr, u8 type, unsigned maxp); static int wmt_udc_start(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *)) { int status = -ENODEV; struct vt8500_ep *ep; // unsigned long flags; DBG("wmt_udc_start()\n"); /* basic sanity tests */ if (!udc) return -ENODEV; if (!driver /* FIXME if otg, check: driver->is_otg*/ || driver->max_speed < USB_SPEED_FULL || !bind // || !driver->unbind || !driver->setup){ // printk(KERN_INFO "gri usb_gadget_probe_driver f2\n"); // printk(KERN_INFO "gri driver=%x driver->speed=%x driver->bind=%x driver->unbind=%x driver->setup=%x\n", // (unsigned int)driver,(unsigned int)driver->speed,(unsigned int)driver->bind,(unsigned int)driver->unbind,(unsigned int)driver->setup); return -EINVAL; } spin_lock_irqsave(&udc->lock, irq_flags); if (udc->driver) { spin_unlock_irqrestore(&udc->lock, irq_flags); return -EBUSY; } /* reset state */ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { ep->irqs = 0; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) continue; /*use_ep(ep, 0);*/ /*UDC_CTRL_REG = UDC_SET_HALT;*/ } udc->ep0_pending = 0; udc->ep0_status_0_byte = 0; udc->ep[0].irqs = 0; udc->softconnect = 1; udc->file_storage_set_halt = 0; /* hook up the driver */ driver->driver.bus = 0; udc->driver = driver; udc->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(&udc->lock, irq_flags); status = bind(&udc->gadget); spin_lock_irqsave(&udc->lock, irq_flags); printk(KERN_INFO "bind to %s --> %d\n", driver->driver.name, status); if (status) { /* %s -> g_file_storage*/ DBG("bind to %s --> %d\n", driver->driver.name, status); // printk(KERN_INFO "gri usb_gadget_probe_driver %d\n", status); udc->gadget.dev.driver = 0; udc->driver = 0; goto done; } DBG("bound to driver %s\n", driver->driver.name);/*udc: bound to driver g_file_storage*/ pUSBMiscControlRegister5 = (unsigned char *)(USB_UDC_REG_BASE + 0x1A0); *pUSBMiscControlRegister5 = 0x01;/*USB in normal operation*/ wmb(); #if 0 /* reset Bulk descriptor control*/ pDevReg->Bulk1EpControl = 0; /* stop the bulk DMA*/ while (pDevReg->Bulk1EpControl & EP_ACTIVE) ; /* wait the DMA stopped*/ pDevReg->Bulk2EpControl = 0; /* stop the bulk DMA*/ while (pDevReg->Bulk2EpControl & EP_ACTIVE) ; /* wait the DMA stopped*/ pDevReg->Bulk3EpControl = 0; /* stop the bulk DMA*/ while (pDevReg->Bulk3EpControl & EP_ACTIVE) ; /* wait the DMA stopped*/ pDevReg->Bulk1DesStatus = 0x00; pDevReg->Bulk2DesStatus = 0x00; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk1DesTbytes0 = 0; pDevReg->Bulk1DesTbytes1 = 0; pDevReg->Bulk1DesTbytes2 = 0; pDevReg->Bulk2DesTbytes0 = 0; pDevReg->Bulk2DesTbytes1 = 0; pDevReg->Bulk2DesTbytes2 = 0; pDevReg->Bulk3DesTbytes0 = 0; pDevReg->Bulk3DesTbytes1 = 0; pDevReg->Bulk3DesTbytes2 = 0; /* enable DMA and run the control endpoint*/ pDevReg->ControlEpControl = EP_RUN + EP_ENABLEDMA; /* enable DMA and run the bulk endpoint*/ pDevReg->Bulk1EpControl = EP_RUN + EP_ENABLEDMA; pDevReg->Bulk2EpControl = EP_RUN + EP_ENABLEDMA; #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpControl = EP_RUN + EP_ENABLEDMA; #else pDevReg->InterruptEpControl = EP_RUN + EP_ENABLEDMA; #endif #endif /* enable DMA and run the interrupt endpoint*/ /* UsbControlRegister.InterruptEpControl = EP_RUN+EP_ENABLEDMA;*/ /* run the USB controller*/ pDevReg->MiscControl3 = 0x3d; pDevReg->PortControl |= PORTCTRL_SELFPOWER;/* Device port control register - 22*/ wmb(); pDevReg->CommandStatus = USBREG_RUNCONTROLLER; wmb(); ControlState = CONTROLSTATE_SETUP; USBState = USBSTATE_DEFAULT; TestMode = 0; wmt_ep_setup_csr("ep0", 0, USB_ENDPOINT_XFER_CONTROL, 64); #if 0 wmt_ep_setup_csr("ep1in-bulk", (USB_DIR_IN | 1), USB_ENDPOINT_XFER_BULK, 512); wmt_ep_setup_csr("ep2out-bulk", (USB_DIR_OUT | 2), USB_ENDPOINT_XFER_BULK, 512); #ifdef USE_BULK3_TO_INTERRUPT wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 28); #else wmt_ep_setup_csr("ep3in-int", (USB_DIR_IN | 3), USB_ENDPOINT_XFER_INT, 8); #endif wmt_ep_setup_csr("ep4in-iso", (USB_DIR_IN | 4), USB_ENDPOINT_XFER_ISO, 384); #endif /* enable all interrupt*/ #ifdef FULL_SPEED_ONLY pDevReg->IntEnable = (INTENABLE_ALL | INTENABLE_FULLSPEEDONLY) ;/*0x70*/ #else pDevReg->IntEnable = INTENABLE_ALL;/*0x70*/ #endif /* set IOC on the Setup decscriptor to accept the Setup request*/ pDevReg->ControlDesControl = CTRLXFER_IOC; wmt_pdma_reset();/*NeilChen*/ // pDevReg->FunctionPatchEn |= 0x20; /* HW attach process evaluation enable bit*/ #ifdef DEBUG_UDC_ISR_TIMER init_timer(&udc->timer); udc->timer.function = wmt_udc_softirq; udc->timer.data = (unsigned long) udc; add_timer(&udc->timer); #endif done: spin_unlock_irqrestore(&udc->lock, irq_flags); return status; } /*int wmt_udc_start ()*/ static int wmt_udc_stop(struct usb_gadget_driver *driver) { // unsigned long flags; int status = -ENODEV; if (!udc) return -ENODEV; if (!driver || driver != udc->driver) return -EINVAL; spin_lock_irqsave(&udc->lock, irq_flags); udc_quiesce(udc); spin_unlock_irqrestore(&udc->lock, irq_flags); driver->unbind(&udc->gadget); udc->gadget.dev.driver = 0; udc->driver = 0; pDevReg->IntEnable &= 0x8F;/*INTENABLE_ALL(0x70)*/ /* set IOC on the Setup decscriptor to accept the Setup request*/ pDevReg->ControlDesControl &= 0x7F;/*CTRLXFER_IOC;*/ if (udc->transceiver) (void) otg_set_peripheral(udc->transceiver->otg, NULL); else { pullup_disable(udc); // pDevReg->FunctionPatchEn &= ~0x20; } if (TestMode != 0x00) { pDevReg->CommandStatus &= 0x1F; pUSBMiscControlRegister5 = (unsigned char *)(USB_UDC_REG_BASE + 0x1A0); *pUSBMiscControlRegister5 = 0x00;/* USB PHY in power down & USB in reset*/ INFO("usb_gadget_unregister_driver() RESET_UDC OK!\n"); TestMode = 0; } DBG("unregistered driver '%s'\n", driver->driver.name); return status; } /*int wmt_udc_stop ()*/ /*-------------------------------------------------------------------------*/ #ifdef CONFIG_USB_vt8500_PROC #include static const char proc_filename[] = "driver/udc"; #define FOURBITS "%s%s%s%s" #define EIGHTBITS FOURBITS FOURBITS static void proc_ep_show(struct seq_file *s, struct vt8500_ep *ep) { } /*proc_ep_show()*/ static char *trx_mode(unsigned m) { switch (m) { case 3: case 0: return "6wire"; case 1: return "4wire"; case 2: return "3wire"; default: return "unknown"; } } static int proc_udc_show(struct seq_file *s, void *_) { return 0; } static int proc_udc_open(struct inode *inode, struct file *file) { return single_open(file, proc_udc_show, 0); } static struct file_operations proc_ops = { .open = proc_udc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static void create_proc_file(void) { struct proc_dir_entry *pde; pde = create_proc_entry(proc_filename, 0, NULL); if (pde) pde->proc_fops = &proc_ops; } static void remove_proc_file(void) { remove_proc_entry(proc_filename, 0); } #else static inline void create_proc_file(void) {} static inline void remove_proc_file(void) {} #endif /*-------------------------------------------------------------------------*/ /* Before this controller can enumerate, we need to pick an endpoint * configuration, or "fifo_mode" That involves allocating 2KB of packet * buffer space among the endpoints we'll be operating. */ static void __init wmt_ep_setup(char *name, u8 addr, u8 type, unsigned maxp) { struct vt8500_ep *ep; VDBG("wmt_ep_setup()\n"); /* OUT endpoints first, then IN*/ ep = &udc->ep[addr & 0x7f]; VDBG("wmt_ep_setup() - %s addr %02x maxp %d\n", name, addr, maxp); strlcpy(ep->name, name, sizeof ep->name); INIT_LIST_HEAD(&ep->queue); ep->bEndpointAddress = addr; ep->bmAttributes = type; ep->double_buf = 0;/*dbuf;*/ ep->udc = udc; ep->toggle_bit = 0; ep->ep.name = ep->name; ep->ep.ops = &wmt_ep_ops;/*struct usb_ep_ops*/ ep->ep.maxpacket = ep->maxpacket = maxp; list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); /*return buf;*/ } /*wmt_ep_setup()*/ static void wmt_udc_release(struct device *dev) { DBG("wmt_udc_release()\n"); complete(udc->done); kfree(udc); udc = 0; } /*wmt_udc_release()*/ static int __init wmt_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) { DBG("wmt_udc_setup()\n"); udc = kmalloc(sizeof *udc, GFP_KERNEL); if (!udc) return -ENOMEM; memset(udc, 0, sizeof *udc); spin_lock_init(&udc->lock); spin_lock_init(&gri_lock); sema_init(&wmt_udc_sem, 1); udc->gadget.ops = &wmt_gadget_ops; udc->gadget.ep0 = &udc->ep[0].ep; INIT_LIST_HEAD(&udc->gadget.ep_list); /*INIT_LIST_HEAD(&udc->iso);*/ udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.name = driver_name; device_initialize(&udc->gadget.dev); //strcpy(udc->gadget.dev.bus_id, "gadget"); dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.release = wmt_udc_release; udc->transceiver = NULL; /* ep0 is special; put it right after the SETUP buffer*/ wmt_ep_setup("ep0", 0, USB_ENDPOINT_XFER_CONTROL, 64); list_del_init(&udc->ep[0].ep.ep_list); #if 1 #if 1 #define VT8430_BULK_EP(name, addr) \ wmt_ep_setup(name "-bulk", addr, \ USB_ENDPOINT_XFER_BULK, 512); /*usb_ch9.h*/ /*#define USB_DIR_OUT 0 *//* to device */ /*#define USB_DIR_IN 0x80 *//* to host */ #define VT8430_INT_EP(name, addr, maxp) \ wmt_ep_setup(name "-int", addr, \ USB_ENDPOINT_XFER_INT, maxp); #define VT8430_ISO_EP(name, addr, maxp) \ wmt_ep_setup(name "-iso", addr, \ USB_ENDPOINT_XFER_ISOC, maxp); #endif VT8430_BULK_EP("ep1in", USB_DIR_IN | 1); VT8430_BULK_EP("ep2out", USB_DIR_OUT | 2); #ifdef USE_BULK3_TO_INTERRUPT VT8430_INT_EP("ep3in", USB_DIR_IN | 3, 512); #else VT8430_INT_EP("ep3in", USB_DIR_IN | 3, 8); #endif VT8430_ISO_EP("ep4in", USB_DIR_IN | 4, 512); #endif udc->ep[0].rndis_buffer_alloc = 0; udc->ep[1].rndis_buffer_alloc = 0; udc->ep[2].rndis_buffer_alloc = 0; udc->ep[3].rndis_buffer_alloc = 0; udc->ep[4].rndis_buffer_alloc = 0; udc->ep[5].rndis_buffer_alloc = 0;//gri udc->ep[6].rndis_buffer_alloc = 0;//gri /*INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf);*/ return 0; } /*wmt_udc_setup()*/ static void wmt_pdma_reset(void) { if (!pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable) pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_Global_Bits.SoftwareReset = 1; wmb(); while (pUdcDmaReg->DMA_Global_Bits.SoftwareReset)/*wait reset complete*/ ; pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable0 = 1; pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable1 = 1; pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable2 = 1; pUdcDmaReg->DMA_Context_Control0_Bis.TransDir = 0; pUdcDmaReg->DMA_Context_Control1_Bis.TransDir = 1; pUdcDmaReg->DMA_Context_Control2_Bis.TransDir = 0; wmb(); /*descriptor initial*/ } /*wmt_pdma_init*/ static void wmt_pdma0_reset(void) { if (!pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable) pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_Global_Bits.SoftwareReset0 = 1; wmb(); while (pUdcDmaReg->DMA_Global_Bits.SoftwareReset0)/*wait reset complete*/ ; pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable0 = 1; pUdcDmaReg->DMA_Context_Control0_Bis.TransDir = 0; wmb(); /*descriptor initial*/ } /*wmt_pdma_init*/ static void wmt_pdma1_reset(void) { if (!pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable) pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_Global_Bits.SoftwareReset1 = 1; wmb(); while (pUdcDmaReg->DMA_Global_Bits.SoftwareReset1)/*wait reset complete*/ ; pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable1 = 1; pUdcDmaReg->DMA_Context_Control1_Bis.TransDir = 1; wmb(); /*descriptor initial*/ } /*wmt_pdma_init*/ #ifdef USE_BULK3_TO_INTERRUPT static void wmt_pdma2_reset(void) { if (!pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable) pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_Global_Bits.SoftwareReset2 = 1; wmb(); while (pUdcDmaReg->DMA_Global_Bits.SoftwareReset2)/*wait reset complete*/ ; pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable2 = 1; pUdcDmaReg->DMA_Context_Control2_Bis.TransDir = 0; wmb(); /*descriptor initial*/ } /*wmt_pdma_init*/ #endif /*static void wmt_pdma_init(struct device *dev)*/ static void wmt_pdma_init(struct device *dev) { UdcRndisEp1VirAddr = (unsigned int) dma_alloc_coherent(dev, (size_t)65536, (dma_addr_t *)(&UdcRndisEp1PhyAddr), GFP_KERNEL|GFP_ATOMIC); UdcRndisEp2VirAddr = (unsigned int) dma_alloc_coherent(dev, (size_t)65536, (dma_addr_t *)(&UdcRndisEp2PhyAddr), GFP_KERNEL|GFP_ATOMIC); UdcRndisEp3VirAddr = (unsigned int) dma_alloc_coherent(dev, (size_t)65536, (dma_addr_t *)(&UdcRndisEp3PhyAddr), GFP_KERNEL|GFP_ATOMIC); UdcPdmaVirAddrLI = (unsigned int) dma_alloc_coherent(pDMADescLI, (size_t)0x100, (dma_addr_t *)(&UdcPdmaPhyAddrLI), GFP_KERNEL|GFP_ATOMIC); UdcPdmaVirAddrSI = (unsigned int) dma_alloc_coherent(pDMADescSI, (size_t)0x100, (dma_addr_t *)(&UdcPdmaPhyAddrSI), GFP_KERNEL|GFP_ATOMIC); UdcPdmaVirAddrLO = (unsigned int) dma_alloc_coherent(pDMADescLO, (size_t)0x100, (dma_addr_t *)(&UdcPdmaPhyAddrLO), GFP_KERNEL|GFP_ATOMIC); UdcPdmaVirAddrSO = (unsigned int) dma_alloc_coherent(pDMADescSO, (size_t)0x100, (dma_addr_t *)(&UdcPdmaPhyAddrSO), GFP_KERNEL|GFP_ATOMIC); #ifdef USE_BULK3_TO_INTERRUPT UdcPdmaVirAddrL2I = (unsigned int) dma_alloc_coherent(pDMADescL2I, (size_t)0x100, (dma_addr_t *)(&UdcPdmaPhyAddrL2I), GFP_KERNEL|GFP_ATOMIC); UdcPdmaVirAddrS2I = (unsigned int) dma_alloc_coherent(pDMADescS2I, (size_t)0x100, (dma_addr_t *)(&UdcPdmaPhyAddrS2I), GFP_KERNEL|GFP_ATOMIC); #endif pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_Global_Bits.SoftwareReset = 1; wmb(); while (pUdcDmaReg->DMA_Global_Bits.SoftwareReset)/*wait reset complete*/ ; pUdcDmaReg->DMA_Global_Bits.DMAConrollerEnable = 1;/*enable DMA*/ pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable0 = 1; pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable1 = 1; pUdcDmaReg->DMA_Context_Control0_Bis.TransDir = 0; pUdcDmaReg->DMA_Context_Control1_Bis.TransDir = 1; #ifdef USE_BULK3_TO_INTERRUPT pUdcDmaReg->DMA_IER_Bits.DMAInterruptEnable2 = 1; pUdcDmaReg->DMA_Context_Control2_Bis.TransDir = 0; #endif wmb(); } /*wmt_pdma_init*/ /*static int __init wmt_udc_probe(struct device *dev)*/ static int __init wmt_udc_probe(struct platform_device *pdev) { /* struct platform_device *odev = to_platform_device(dev);*/ struct device *dev = &pdev->dev; int status = -ENODEV; struct usb_phy *xceiv = 0; DBG("wmt_udc_probe()\n"); /*UDC Register Space 0x400~0x7EF*/ INIT_LIST_HEAD (&done_main_list); b_pullup = 0; pDevReg = (struct UDC_REGISTER *)USB_UDC_REG_BASE; pUdcDmaReg = (struct UDC_DMA_REG *)USB_UDC_DMA_REG_BASE; pSetupCommand = (PSETUPCOMMAND)(USB_UDC_REG_BASE + 0x300); pSetupCommandBuf = (unsigned char *)(USB_UDC_REG_BASE + 0x300); SetupBuf = (UCHAR *)(USB_UDC_REG_BASE + 0x340); IntBuf = (UCHAR *)(USB_UDC_REG_BASE + 0x40); pUSBMiscControlRegister5 = (unsigned char *)(USB_UDC_REG_BASE + 0x1A0); #ifdef OTGIP /*UHDC Global Register Space 0x7F0~0x7F7*/ pGlobalReg = (struct USB_GLOBAL_REG *) USB_GLOBAL_REG_BASE; #endif *pUSBMiscControlRegister5 = 0x01; pDevReg->CommandStatus &= 0x1F; pDevReg->CommandStatus |= USBREG_RESETCONTROLLER; wmb(); while (pDevReg->CommandStatus & USBREG_RESETCONTROLLER) ; wmt_pdma_init(dev); pDevReg->Bulk1EpControl = 0; /* stop the bulk DMA*/ wmb(); while (pDevReg->Bulk1EpControl & EP_ACTIVE) /* wait the DMA stopped*/ ; pDevReg->Bulk2EpControl = 0; /* stop the bulk DMA*/ wmb(); while (pDevReg->Bulk2EpControl & EP_ACTIVE) /* wait the DMA stopped*/ ; pDevReg->Bulk1DesStatus = 0x00; pDevReg->Bulk2DesStatus = 0x00; pDevReg->Bulk1DesTbytes0 = 0; pDevReg->Bulk1DesTbytes1 = 0; pDevReg->Bulk1DesTbytes2 = 0; pDevReg->Bulk2DesTbytes0 = 0; pDevReg->Bulk2DesTbytes1 = 0; pDevReg->Bulk2DesTbytes2 = 0; #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpControl = 0; /* stop the bulk DMA*/ wmb(); while (pDevReg->Bulk3EpControl & EP_ACTIVE) /* wait the DMA stopped*/ ; pDevReg->Bulk3DesStatus = 0x00; pDevReg->Bulk3DesTbytes0 = 0; pDevReg->Bulk3DesTbytes1 = 0; pDevReg->Bulk3DesTbytes2 = 0; #endif /* enable DMA and run the control endpoint*/ wmb(); pDevReg->ControlEpControl = EP_RUN + EP_ENABLEDMA; /* enable DMA and run the bulk endpoint*/ pDevReg->Bulk1EpControl = EP_RUN + EP_ENABLEDMA; pDevReg->Bulk2EpControl = EP_RUN + EP_ENABLEDMA; #ifdef USE_BULK3_TO_INTERRUPT pDevReg->Bulk3EpControl = EP_RUN + EP_ENABLEDMA; #else pDevReg->InterruptEpControl = EP_RUN + EP_ENABLEDMA; #endif wmb(); /* enable DMA and run the interrupt endpoint*/ /* UsbControlRegister.InterruptEpControl = EP_RUN+EP_ENABLEDMA;*/ /* run the USB controller*/ pDevReg->MiscControl3 = 0x3d; /* HW attach process evaluation enable bit For WM3426 and after project*/ /*pDevReg->FunctionPatchEn |= 0x20;*/ #ifdef HW_BUG_HIGH_SPEED_PHY pDevReg->MiscControl0 &= ~0x80; #endif pDevReg->MiscControl0 |= 0x02; wmb(); pDevReg->CommandStatus = USBREG_RUNCONTROLLER; ControlState = CONTROLSTATE_SETUP; USBState = USBSTATE_DEFAULT; TestMode = 0; status = wmt_udc_setup(pdev, xceiv); if (status) goto cleanup0; xceiv = 0; /*udc->chip_version = tmp8;*/ /* "udc" is now valid*/ pullup_disable(udc); udc->gadget.is_otg = 0;/*(config->otg != 0);*/ udc->dev = dev; udc->gadget.max_speed = USB_SPEED_HIGH;; udc->ep0_status_0_byte = 0; udc->usb_connect = 0; /* USB general purpose IRQ: ep0, state changes, dma, etc*/ status = request_irq(UDC_IRQ_USB, wmt_udc_irq, // (SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM), driver_name, udc); // (IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM), driver_name, udc); (IRQF_SHARED | IRQF_SAMPLE_RANDOM), driver_name, udc);//gri pDevReg->SelfPowerConnect |= 0x10;//Neil #ifndef OTGIP status = request_irq(UDC_IRQ_DMA, wmt_udc_dma_irq, // (SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM), driver_name, udc); // (IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM), driver_name, udc); (IRQF_SHARED | IRQF_SAMPLE_RANDOM), driver_name, udc); #endif /*SA_SAMPLE_RANDOM, driver_name, udc);*/ if (status != 0) { ERR("can't get irq %d, err %d\n", UDC_IRQ_USB, status); goto cleanup1; } else INFO("wmt_udc_probe - request_irq(0x%02X) pass!\n", UDC_IRQ_USB); create_proc_file(); status = device_add(&udc->gadget.dev); if (status) goto cleanup4; status = usb_add_gadget_udc(&pdev->dev, &udc->gadget); initial_test_fiq(); if (!status) return 0; cleanup4: remove_proc_file(); /*cleanup2:*/ free_irq(UDC_IRQ_USB, udc); INFO("wmt_udc_probe - free_irq(0x%02X)?\n", UDC_IRQ_USB); cleanup1: kfree(udc); udc = 0; cleanup0: if (xceiv) usb_put_transceiver(xceiv); /*release_mem_region(odev->resource[0].start,*/ /* odev->resource[0].end - odev->resource[0].start + 1);*/ return status; } /*wmt_udc_probe()*/ static int __exit wmt_udc_remove(struct platform_device *pdev) { /*struct platform_device *odev = to_platform_device(dev);*/ DECLARE_COMPLETION(done); DBG("wmt_udc_remove()\n"); if (!udc) return -ENODEV; udc->done = &done; pullup_disable(udc); if (udc->transceiver) { usb_put_transceiver(udc->transceiver); udc->transceiver = 0; } /*UDC_SYSCON1_REG = 0;*/ remove_proc_file(); free_irq(UDC_IRQ_USB, udc); device_unregister(&udc->gadget.dev); wait_for_completion(&done); return 0; } /*wmt_udc_remove()*/ /* suspend/resume/wakeup from sysfs (echo > power/state) */ static int wmt_udc_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { if (event == PM_SUSPEND_PREPARE) { if (udc->driver){ run_script(action_off_line); } gadget_connect=0; down(&wmt_udc_sem); pullup_disable(udc); up(&wmt_udc_sem); } else if (event == PM_POST_SUSPEND) { down(&wmt_udc_sem); pullup_enable(udc); up(&wmt_udc_sem); wmt_wakeup(&udc->gadget); } return NOTIFY_OK; } static struct notifier_block wmt_udc_pm_notifier = { .notifier_call = wmt_udc_pm_notify, }; static int wmt_udc_suspend(struct platform_device *pdev, pm_message_t state) { DBG("wmt_udc_suspend()\n"); printk(KERN_INFO "wmt_udc_suspend\n"); //gri #if 0 if (udc->driver){ run_script(action_off_line); } gadget_connect=0; run_script(action_mount); #endif pDevReg->CommandStatus &= 0x1F; pUSBMiscControlRegister5 = (unsigned char *)(USB_UDC_REG_BASE + 0x1A0); /**pUSBMiscControlRegister5 = 0x02;// USB PHY in power down & USB in reset*/ *pUSBMiscControlRegister5 = 0x00;/*USB in reset*/ wmb(); TestMode = 0; #if 0 down(&wmt_udc_sem); pullup_disable(udc); up(&wmt_udc_sem); #endif /* if ((state == 3) && (level == 3))*/ /* *(volatile unsigned int *)(PM_CTRL_BASE_ADDR + 0x254) &= ~0x00000080;*/ /*DPM needed*/ *(volatile unsigned char*)(USB_IP_BASE + 0x249) |= 0x04; return 0; } /*wmt_udc_suspend()*/ static int wmt_udc_resume(struct platform_device *pdev) { #if 0 DBG("wmt_udc_resume()\n"); printk(KERN_INFO "wmt_udc_resume\n"); //gri down(&wmt_udc_sem); reset_udc(); pullup_enable(udc); up(&wmt_udc_sem); return wmt_wakeup(&udc->gadget); #endif reset_udc(); return 0; } /*wmt_udc_resume()*/ /*-------------------------------------------------------------------------*/ static struct platform_driver udc_driver = { .driver.name = (char *) driver_name, .probe = wmt_udc_probe, .remove = __exit_p(wmt_udc_remove), .suspend = wmt_udc_suspend, .resume = wmt_udc_resume, }; static struct resource wmt_udc_resources[] = { [0] = { .start = (USB_IP_BASE + 0x2000), .end = (USB_IP_BASE + 0x2400), .flags = IORESOURCE_MEM, }, }; static u64 wmt_udc_dma_mask = 0xFFFFF000; static struct platform_device wmt_udc_device = { .name = (char *) driver_name, .id = 0, .dev = { .dma_mask = &wmt_udc_dma_mask, .coherent_dma_mask = ~0, }, .num_resources = ARRAY_SIZE(wmt_udc_resources), .resource = wmt_udc_resources, }; void wmt_cleanup_done_thread(int number) { unsigned long flags; struct usb_composite_dev *cdev = get_gadget_data(&(udc->gadget)); #if 1 if(number == 1) { if(in_interrupt()) return; if(spin_is_locked(&cdev->lock)){ //local_irq_save(flags); spin_unlock(&cdev->lock); //local_irq_enable(); //schedule_work(&done_thread); flush_work_sync(&done_thread); //local_irq_restore(flags); spin_lock(&cdev->lock); }else{ flush_work_sync(&done_thread); } //wmt_ep_disable(&udc->ep[0]); spin_lock_irqsave(&udc->lock, flags); nuke(&udc->ep[0],ESHUTDOWN); spin_unlock_irqrestore(&udc->lock, flags); }else if(number == 2) { }else{ //flush_work_sync(&mount_thread); printk("erro parameter:%s\n",__func__); } #endif } EXPORT_SYMBOL(wmt_cleanup_done_thread); static int __init udc_init(void) { INFO("%s, version: " DRIVER_VERSION "%s\n", driver_desc, use_dma ? " (dma)" : ""); DBG("udc_init()\n"); //INIT_WORK(&online_thread, run_online); INIT_WORK(&offline_thread, run_offline); INIT_WORK(&done_thread, run_done); INIT_WORK(&chkiso_thread, run_chkiso); platform_device_register(&wmt_udc_device); register_pm_notifier(&wmt_udc_pm_notifier); return platform_driver_register(&udc_driver); } /*udc_init()*/ module_init(udc_init); static void __exit udc_exit(void) { DBG("udc_exit()\n"); //driver_unregister(&udc_driver); platform_driver_unregister(&udc_driver); platform_device_unregister(&wmt_udc_device); } /*udc_exit()*/ module_exit(udc_exit); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL");