[PATCH 96/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00112509 : [MX37] failed to test our MSC driver with USBCV 1.3.

Brad Figg brad.figg at canonical.com
Thu Jul 9 16:49:26 UTC 2009


      1. pass msc class driver test with usbcv.
      2. set_bulk_out_req_length should set 512, not 31.
      3. fixed the missing ACK issue.
      4. remove the compile warning.

Signed-off-by: Albert Chen <r65187 at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
 drivers/usb/gadget/arcotg_udc.c   |  218 +++++++++++++++++++++++--------------
 drivers/usb/gadget/arcotg_udc.h   |    3 +-
 drivers/usb/gadget/file_storage.c |    2 +
 3 files changed, 139 insertions(+), 84 deletions(-)

diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index afd9ad2..2d3f89b 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -89,6 +89,8 @@ fsl_ep0_desc = {
 };
 static const size_t g_iram_size = IRAM_TD_PPH_SIZE;
 
+typedef int (*dev_sus)(struct device *dev, pm_message_t state);
+typedef int (*dev_res) (struct device *dev);
 static int udc_suspend(struct fsl_udc *udc);
 static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state);
 static int fsl_udc_resume(struct platform_device *pdev);
@@ -379,9 +381,11 @@ static void dr_controller_run(struct fsl_udc *udc)
 	udc->stopped = 0;
 
 	/* Set controller to Run */
-	temp = fsl_readl(&dr_regs->usbcmd);
-	temp |= USB_CMD_RUN_STOP;
-	fsl_writel(temp, &dr_regs->usbcmd);
+	if (udc->driver) {
+		temp = fsl_readl(&dr_regs->usbcmd);
+		temp |= USB_CMD_RUN_STOP;
+		fsl_writel(temp, &dr_regs->usbcmd);
+	}
 
 	return;
 }
@@ -922,8 +926,8 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	int is_iso = 0;
 
 	/* catch various bogus parameters */
-	if (!_req || !req->req.complete || !req->req.buf
-			|| !list_empty(&req->queue)) {
+	if (!_req || !req->req.buf || (ep_index(ep)
+				      && !list_empty(&req->queue))) {
 		VDBG("%s, bad params\n", __func__);
 		return -EINVAL;
 	}
@@ -978,10 +982,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		return -ENOMEM;
 	}
 
-	/* Update ep0 state */
-	if ((ep_index(ep) == 0))
-		udc->ep0_state = DATA_STATE_XMIT;
-
 	/* irq handler advances the queue */
 	if (req != NULL)
 		list_add_tail(&req->queue, &ep->queue);
@@ -1111,7 +1111,6 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
 	spin_unlock_irqrestore(&ep->udc->lock, flags);
 
 	if (ep_index(ep) == 0) {
-		udc->ep0_state = WAIT_FOR_SETUP;
 		udc->ep0_dir = 0;
 	}
 out:
@@ -1323,7 +1322,6 @@ static void ep0stall(struct fsl_udc *udc)
 	tmp = fsl_readl(&dr_regs->endptctrl[0]);
 	tmp |= EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL;
 	fsl_writel(tmp, &dr_regs->endptctrl[0]);
-	udc->ep0_state = WAIT_FOR_SETUP;
 	udc->ep0_dir = 0;
 }
 
@@ -1340,24 +1338,12 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 		udc->ep0_dir = USB_DIR_OUT;
 
 	ep = &udc->eps[0];
-	udc->ep0_state = WAIT_FOR_OUT_STATUS;
 
 	req->ep = ep;
 	req->req.length = 0;
 	req->req.status = -EINPROGRESS;
-	req->req.actual = 0;
-	req->req.complete = NULL;
-	req->dtd_count = 0;
-
-	if (fsl_req_to_dtd(req) == 0)
-		status = fsl_queue_td(ep, req);
-	else
-		return -ENOMEM;
-
-	if (status)
-		ERR("Can't queue ep0 status request \n");
-	list_add_tail(&req->queue, &ep->queue);
 
+	status = fsl_ep_queue(&ep->ep, &req->req, GFP_ATOMIC);
 	return status;
 }
 
@@ -1423,32 +1409,24 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 	}
 
 	udc->ep0_dir = USB_DIR_IN;
-	/* Borrow the per device status_req */
-	req = udc->status_req;
+	/* Borrow the per device data_req */
+	/* status_req had been used to prime status */
+	req = udc->data_req;
 	/* Fill in the reqest structure */
 	*((u16 *) req->req.buf) = cpu_to_le16(tmp);
 	req->ep = ep;
 	req->req.length = 2;
-	req->req.status = -EINPROGRESS;
-	req->req.actual = 0;
-	req->req.complete = NULL;
-	req->dtd_count = 0;
-
-	/* prime the data phase */
-	if ((fsl_req_to_dtd(req) == 0))
-		status = fsl_queue_td(ep, req);
-	else			/* no mem */
-		goto stall;
 
+	status = fsl_ep_queue(&ep->ep, &req->req, GFP_ATOMIC);
 	if (status) {
+		udc_reset_ep_queue(udc, 0);
 		ERR("Can't respond to getstatus request \n");
 		goto stall;
 	}
-	list_add_tail(&req->queue, &ep->queue);
-	udc->ep0_state = DATA_STATE_XMIT;
 	return;
 stall:
 	ep0stall(udc);
+
 }
 
 static void setup_received_irq(struct fsl_udc *udc,
@@ -1460,6 +1438,15 @@ static void setup_received_irq(struct fsl_udc *udc,
 
 	udc_reset_ep_queue(udc, 0);
 
+	if (wLength) {
+		int dir;
+		dir = EP_DIR_IN;
+		if (setup->bRequestType & USB_DIR_IN) {
+			dir = EP_DIR_OUT;
+		}
+		if (ep0_prime_status(udc, dir))
+			ep0stall(udc);
+	}
 	/* We process some stardard setup requests here */
 	switch (setup->bRequest) {
 	case USB_REQ_GET_STATUS:
@@ -1550,11 +1537,11 @@ static void setup_received_irq(struct fsl_udc *udc,
 				?  USB_DIR_IN : USB_DIR_OUT;
 		spin_unlock(&udc->lock);
 		if (udc->driver->setup(&udc->gadget,
-				&udc->local_setup_buff) < 0)
+				&udc->local_setup_buff) < 0) {
+			/* cancel status phase */
+			udc_reset_ep_queue(udc, 0);
 			ep0stall(udc);
-		spin_lock(&udc->lock);
-		udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
-				?  DATA_STATE_XMIT : DATA_STATE_RECV;
+		}
 	} else {
 		/* No data phase, IN status from gadget */
 		udc->ep0_dir = USB_DIR_IN;
@@ -1562,9 +1549,8 @@ static void setup_received_irq(struct fsl_udc *udc,
 		if (udc->driver->setup(&udc->gadget,
 				&udc->local_setup_buff) < 0)
 			ep0stall(udc);
-		spin_lock(&udc->lock);
-		udc->ep0_state = WAIT_FOR_OUT_STATUS;
 	}
+	spin_lock(&udc->lock);
 }
 
 /* Process request for Data or Status phase of ep0
@@ -1580,28 +1566,6 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
 	}
 
 	done(ep0, req, 0);
-
-	switch (udc->ep0_state) {
-	case DATA_STATE_XMIT:
-		/* receive status phase */
-		if (ep0_prime_status(udc, EP_DIR_OUT))
-			ep0stall(udc);
-		break;
-	case DATA_STATE_RECV:
-		/* send status phase */
-		if (ep0_prime_status(udc, EP_DIR_IN))
-			ep0stall(udc);
-		break;
-	case WAIT_FOR_OUT_STATUS:
-		udc->ep0_state = WAIT_FOR_SETUP;
-		break;
-	case WAIT_FOR_SETUP:
-		ERR("Unexpect ep0 packets \n");
-		break;
-	default:
-		ep0stall(udc);
-		break;
-	}
 }
 
 /* Tripwire mechanism to ensure a setup packet payload is extracted without
@@ -1820,7 +1784,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
 
 		/* If the ep is configured */
 		if (curr_ep->name == NULL) {
-			WARN("Invalid EP?");
+			INFO("Invalid EP?");
 			continue;
 		}
 
@@ -1900,6 +1864,21 @@ static void suspend_irq(struct fsl_udc *udc)
 		udc->driver->suspend(&udc->gadget);
 }
 
+#ifdef CONFIG_USB_GADGET_WAKE_UP
+/* Process Wake up interrupt */
+static void wake_up_irq(struct fsl_udc *udc)
+{
+	u32 irq_src;
+
+	pr_debug("%s\n", __func__);
+
+	/* disable wake up irq */
+	irq_src = fsl_readl(&dr_regs->usbctrl);
+	irq_src &= ~USB_CTRL_OTG_WUIE;
+	fsl_writel(irq_src, &dr_regs->usbctrl);
+}
+#endif
+
 static void bus_resume(struct fsl_udc *udc)
 {
 	udc->usb_state = udc->resume_state;
@@ -1928,7 +1907,6 @@ static int reset_queues(struct fsl_udc *udc)
 static void reset_irq(struct fsl_udc *udc)
 {
 	u32 temp;
-	unsigned long timeout;
 
 	/* Clear the device address */
 	temp = fsl_readl(&dr_regs->deviceaddr);
@@ -1939,7 +1917,6 @@ static void reset_irq(struct fsl_udc *udc)
 	/* Clear usb state */
 	udc->resume_state = 0;
 	udc->ep0_dir = 0;
-	udc->ep0_state = WAIT_FOR_SETUP;
 	udc->remote_wakeup = 0;	/* default to 0 on reset */
 	udc->gadget.b_hnp_enable = 0;
 	udc->gadget.a_hnp_support = 0;
@@ -1991,6 +1968,25 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
 	irqreturn_t status = IRQ_NONE;
 	unsigned long flags;
 
+#ifdef CONFIG_USB_GADGET_WAKE_UP
+	spin_lock_irqsave(&udc->lock, flags);
+	/* check USBCTRL register to see if wake up irq */
+	irq_src =  fsl_readl(&dr_regs->usbctrl);
+	if (irq_src & USB_CTRL_OTG_WUIR) {
+		wake_up_irq(udc);
+		irq_src = fsl_readl(&dr_regs->usbsts) &
+			fsl_readl(&dr_regs->usbintr);
+		if (irq_src)
+			udc->stopped = 0;
+		else
+			status = IRQ_HANDLED;
+	}
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	if (status == IRQ_HANDLED)
+		return IRQ_HANDLED;
+#endif
+
 	/* Disable ISR for OTG host mode */
 	if (udc->stopped)
 		return IRQ_NONE;
@@ -2101,8 +2097,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 		printk(KERN_INFO "Suspend udc for OTG auto detect\n");
 
 		/* export udc suspend/resume call to OTG */
-		udc_controller->gadget.dev.driver->suspend = fsl_udc_suspend;
-		udc_controller->gadget.dev.driver->resume = fsl_udc_resume;
+		udc_controller->gadget.dev.driver->suspend = (dev_sus)fsl_udc_suspend;
+		udc_controller->gadget.dev.driver->resume = (dev_res)fsl_udc_resume;
 
 		/* connect to bus through transceiver */
 		if (udc_controller->transceiver) {
@@ -2120,7 +2116,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 		/* Enable DR IRQ reg and Set usbcmd reg  Run bit */
 		dr_controller_run(udc_controller);
 		udc_controller->usb_state = USB_STATE_ATTACHED;
-		udc_controller->ep0_state = WAIT_FOR_SETUP;
 		udc_controller->ep0_dir = 0;
 	}
 	printk(KERN_INFO "%s: bind to driver %s \n",
@@ -2153,7 +2148,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	/* in fact, no needed */
 	udc_controller->usb_state = USB_STATE_ATTACHED;
-	udc_controller->ep0_state = WAIT_FOR_SETUP;
 	udc_controller->ep0_dir = 0;
 
 	/* stand operation */
@@ -2509,6 +2503,11 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
 	/* allocate a small amount of memory to get valid address */
 	udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
 	udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf);
+	/* Initialize ep0 data request structure */
+	udc->data_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
+			struct fsl_req, req);
+	udc->data_req->req.buf = kmalloc(8, GFP_KERNEL);
+	udc->data_req->req.dma = virt_to_phys(udc->data_req->req.buf);
 
 	udc->resume_state = USB_STATE_NOTATTACHED;
 	udc->usb_state = USB_STATE_POWERED;
@@ -2606,11 +2605,17 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		goto err1a;
 	}
 #endif
-	dr_regs = ioremap(res->start, resource_size(res));
 
-	if (!dr_regs) {
-		ret = -ENOMEM;
-		goto err1;
+	if ((pdata->port_enables & FSL_USB2_DONT_REMAP) == 0) {
+		dr_regs = ioremap(res->start, resource_size(res));
+		if (!dr_regs) {
+			ret = -ENOMEM;
+			goto err1;
+		}
+		udc_controller->dr_remapped = !0;
+	} else {
+		dr_regs = (void *)res->start;
+		dev_warn(&pdev->dev, "does not remap its address space\n");
 	}
 	pdata->regs = (void *)dr_regs;
 	/*
@@ -2739,7 +2744,8 @@ err2:
 	if (pdata->platform_uninit)
 		pdata->platform_uninit(pdata);
 err2a:
-	iounmap(dr_regs);
+	if (udc_controller->dr_remapped)
+		iounmap((u8 __iomem *)dr_regs);
 err1:
 	if (!udc_controller->transceiver)
 		release_mem_region(res->start, resource_size(res));
@@ -2769,6 +2775,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 	/* Free allocated memory */
 	kfree(udc_controller->status_req->req.buf);
 	kfree(udc_controller->status_req);
+	kfree(udc_controller->data_req->req.buf);
+	kfree(udc_controller->data_req);
 	kfree(udc_controller->eps);
 #ifdef POSTPONE_FREE_LAST_DTD
 	if (last_free_td != NULL)
@@ -2777,7 +2785,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 #endif
 	dma_pool_destroy(udc_controller->td_pool);
 	free_irq(udc_controller->irq, udc_controller);
-	iounmap(dr_regs);
+	if (udc_controller->dr_remapped)
+		iounmap((u8 __iomem *)dr_regs);
 
 #ifndef CONFIG_USB_OTG
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2823,12 +2832,12 @@ static int udc_suspend(struct fsl_udc *udc)
 		return 0;
 	}
 
-	printk(KERN_INFO "USB Gadget suspended\n");
-
 	/* stop the controller */
 	usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
 	fsl_writel(usbcmd, &dr_regs->usbcmd);
 
+	printk(KERN_INFO "USB Gadget suspended\n");
+
 	udc->stopped = 1;
 	return 0;
 }
@@ -2839,6 +2848,35 @@ static int udc_suspend(struct fsl_udc *udc)
  -----------------------------------------------------------------*/
 static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	unsigned int port_status, temp;
+
+	if ((udc_controller->usb_state > USB_STATE_POWERED) &&
+			(udc_controller->usb_state < USB_STATE_SUSPENDED))
+		return -EBUSY;
+
+#ifdef CONFIG_USB_GADGET_WAKE_UP
+	temp = fsl_readl(&dr_regs->usbctrl);
+	/* if usb wake up irq is disabled, enable it */
+	if (!(temp & USB_CTRL_OTG_WUIE)) {
+		temp |= USB_CTRL_OTG_WUIE;
+		fsl_writel(temp, &dr_regs->usbctrl);
+	}
+#else
+	temp = fsl_readl(&dr_regs->usbctrl);
+	/* if usb wake up irq is enabled, disable it */
+	if (temp & USB_CTRL_OTG_WUIE) {
+		temp &= ~USB_CTRL_OTG_WUIE;
+		fsl_writel(temp, &dr_regs->usbctrl);
+	}
+#endif
+
+	/* close UBS PHY clock if PHCD is 0 */
+	port_status = fsl_readl(&dr_regs->portsc1);
+	if (!(port_status & PORTSCX_PHY_LOW_POWER_SPD)) {
+		port_status |= PORTSCX_PHY_LOW_POWER_SPD;
+		fsl_writel(port_status, &dr_regs->portsc1);
+	}
+
 	return udc_suspend(udc_controller);
 }
 
@@ -2863,11 +2901,27 @@ static int fsl_udc_resume(struct platform_device *pdev)
 
 	/* Enable DR irq reg and set controller Run */
 	if (udc_controller->stopped) {
+		u32 temp;
+
+#ifdef CONFIG_USB_GADGET_WAKE_UP
+		/* disable wake up irq */
+		temp = fsl_readl(&dr_regs->usbctrl);
+		temp &= ~UCTRL_OWIE;
+		fsl_writel(temp, &dr_regs->usbctrl);
+#endif
+
+		/* Enable PHY clock if it's disabled */
+		temp = fsl_readl(&dr_regs->portsc1);
+		if (temp & PORTSCX_PHY_LOW_POWER_SPD) {
+			temp &= ~PORTSCX_PHY_LOW_POWER_SPD;
+			fsl_writel(temp, &dr_regs->portsc1);
+			mdelay(1);
+		}
+
 		dr_controller_setup(udc_controller);
 		dr_controller_run(udc_controller);
 	}
 	udc_controller->usb_state = USB_STATE_ATTACHED;
-	udc_controller->ep0_state = WAIT_FOR_SETUP;
 	udc_controller->ep0_dir = 0;
 
 	printk(KERN_INFO "USB Gadget resumed\n");
diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h
index 447aef8..b966f32 100644
--- a/drivers/usb/gadget/arcotg_udc.h
+++ b/drivers/usb/gadget/arcotg_udc.h
@@ -566,6 +566,7 @@ struct fsl_udc {
 
 	struct ep_queue_head *ep_qh;	/* Endpoints Queue-Head */
 	struct fsl_req *status_req;	/* ep0 status request */
+	struct fsl_req *data_req;	/* ep0 data request */
 	struct dma_pool *td_pool;	/* dma pool for DTD */
 	enum fsl_usb2_phy_modes phy_mode;
 
@@ -578,7 +579,6 @@ struct fsl_udc {
 	u32 resume_state;	/* USB state to resume */
 	u32 usb_state;		/* USB current state */
 	u32 usb_next_state;	/* USB next state */
-	u32 ep0_state;		/* Endpoint zero state */
 	u32 ep0_dir;		/* Endpoint zero direction: can be
 				   USB_DIR_IN or USB_DIR_OUT */
 	u32 usb_sof_count;	/* SOF count */
@@ -634,7 +634,6 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length)
 #endif
 
 #define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
 #define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index d77ad4a..2529b1f 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -712,8 +712,10 @@ static void set_bulk_out_req_length(struct fsg_dev *fsg,
 	if (rem > 0)
 		length += fsg->bulk_out_maxpacket - rem;
 	bh->outreq->length = length;
+#if 0
 	if (bh->bulk_out_intended_length == 31)
 		bh->outreq->length = 31;
+#endif
 }
 
 static struct fsg_dev			*the_fsg;
-- 
1.6.0.4





More information about the kernel-team mailing list