summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/udc_wmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/udc_wmt.c')
-rwxr-xr-xdrivers/usb/gadget/udc_wmt.c4699
1 files changed, 4699 insertions, 0 deletions
diff --git a/drivers/usb/gadget/udc_wmt.c b/drivers/usb/gadget/udc_wmt.c
new file mode 100755
index 00000000..c239e3d8
--- /dev/null
+++ b/drivers/usb/gadget/udc_wmt.c
@@ -0,0 +1,4699 @@
+/*
+ * 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 <generated/autoconf.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/suspend.h>
+
+
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/mach-types.h>
+#include <linux/usb/composite.h>
+
+#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 <linux/seq_file.h>
+
+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");