From 05f6dc48a5c494371d3704eb916b90d9dc0b55ac Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 28 Dec 2011 11:34:55 +0800 Subject: [PATCH 1/1] android_usb: enable android usb at mx53 QSB board - Update f_adb file with current kernel version - Fix gadget->speed problem during the probe - Fix enable/disable android gadget problem at freescale platform - Apply some udc enhancement, mainly is for queue qHD/dTD Mass storage and ADB function is tested with Linaro 4.0 android rootfs Signed-off-by: Peter Chen --- drivers/usb/gadget/android.c | 20 ++++++++++++++++++-- drivers/usb/gadget/arcotg_udc.c | 18 +++++++++++------- drivers/usb/gadget/f_adb.c | 14 +++++++++++++- 3 files changed, 42 insertions(+), 10 deletions(-) mode change 100644 => 100755 drivers/usb/gadget/arcotg_udc.c diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index fa313ed..c1a06a9 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -806,6 +806,7 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, struct android_dev *dev = dev_get_drvdata(pdev); struct usb_composite_dev *cdev = dev->cdev; int enabled = 0; + unsigned long flags; sscanf(buff, "%d", &enabled); if (enabled && !dev->enabled) { @@ -818,10 +819,24 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol; usb_add_config(cdev, &android_config_driver, android_bind_config); - usb_gadget_connect(cdev->gadget); + spin_lock_irqsave(&cdev->lock, flags); + if (dev->connected) { + usb_gadget_disconnect(cdev->gadget); + mdelay(10); + usb_gadget_connect(cdev->gadget); + usb_gadget_vbus_connect(cdev->gadget); + } + spin_unlock_irqrestore(&cdev->lock, flags); dev->enabled = true; } else if (!enabled && dev->enabled) { - usb_gadget_disconnect(cdev->gadget); + cdev->next_string_id = 0; + spin_lock_irqsave(&cdev->lock, flags); + if (dev->connected) { + /* Cancel pending control requests */ + usb_gadget_disconnect(cdev->gadget); + usb_ep_dequeue(cdev->gadget->ep0, cdev->req); + } + spin_unlock_irqrestore(&cdev->lock, flags); usb_remove_config(cdev, &android_config_driver); dev->enabled = false; } else { @@ -1018,6 +1033,7 @@ static struct usb_composite_driver android_usb_driver = { .dev = &device_desc, .strings = dev_strings, .unbind = android_usb_unbind, + .max_speed = USB_SPEED_HIGH, }; static int diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c old mode 100644 new mode 100755 index bf09184..5ab84f3 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -875,6 +875,7 @@ static void update_qh(struct fsl_req *req) | EP_QUEUE_HEAD_STATUS_HALT)); dQH->size_ioc_int_sts &= temp; + wmb(); /* Prime endpoint by writing 1 to ENDPTPRIME */ temp = ep_is_in(ep) ? (1 << (ep_index(ep) + 16)) @@ -908,6 +909,7 @@ static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) lastreq->tail->next_td_ptr = cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); } + wmb(); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) goto out; @@ -1593,6 +1595,10 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, ERR("Can't respond to getstatus request \n"); goto stall; } + + if (ep0_prime_status(udc, EP_DIR_OUT)) + ep0stall(udc); + return; stall: ep0stall(udc); @@ -1881,7 +1887,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, total += actual; errors = hc32_to_cpu(curr_td->size_ioc_sts) & DTD_ERROR_MASK; - if (errors) { + if (errors & DTD_ERROR_MASK) { if (errors & DTD_STATUS_HALTED) { ERR("dTD error %08x QH=%d\n", errors, pipe); /* Clear the errors and Halt condition */ @@ -1902,7 +1908,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, status = -EILSEQ; break; } else - ERR("Unknown error has occured (0x%x)!\r\n", + ERR("Unknown error has occurred (0x%x)!\n", errors); } else if (hc32_to_cpu(curr_td->size_ioc_sts) @@ -2300,14 +2306,12 @@ static int fsl_udc_start(struct usb_gadget_driver *driver, { int retval = -ENODEV; unsigned long flags = 0; - if (!udc_controller) return -ENODEV; - if (!bind || !driver || (driver->speed != USB_SPEED_FULL - && driver->speed != USB_SPEED_HIGH) - || !driver->disconnect - || !driver->setup) + if (!driver || (driver->speed != USB_SPEED_FULL + && driver->speed != USB_SPEED_HIGH) + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; if (udc_controller->driver) diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c index ae881cb..933c714 100644 --- a/drivers/usb/gadget/f_adb.c +++ b/drivers/usb/gadget/f_adb.c @@ -325,6 +325,8 @@ requeue_req: pr_debug("rx %p %d\n", req, req->actual); xfer = (req->actual < count) ? req->actual : count; + /* return actual length to app */ + r = xfer; if (copy_to_user(buf, req->buf, xfer)) r = -EFAULT; @@ -429,7 +431,7 @@ static int adb_release(struct inode *ip, struct file *fp) } /* file operations for ADB device /dev/android_adb */ -static struct file_operations adb_fops = { +static const struct file_operations adb_fops = { .owner = THIS_MODULE, .read = adb_read, .write = adb_write, @@ -508,9 +510,19 @@ static int adb_function_set_alt(struct usb_function *f, int ret; DBG(cdev, "adb_function_set_alt intf: %d alt: %d\n", intf, alt); + + ret = config_ep_by_speed(cdev->gadget, f, dev->ep_in); + if (ret) + return ret; + ret = usb_ep_enable(dev->ep_in); if (ret) return ret; + + ret = config_ep_by_speed(cdev->gadget, f, dev->ep_out); + if (ret) + return ret; + ret = usb_ep_enable(dev->ep_out); if (ret) { usb_ep_disable(dev->ep_in); -- 1.7.0.4