summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2012-05-11 14:25:43 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-11 23:43:21 (GMT)
commitef15e5490edc7edf808d3477ab32e0e320792f65 (patch)
treec6c8a4a921f6ec27cf0ad576444948e6a1ecc440
parent405b84487438efa1360740a70ec3e3cd1a90bd62 (diff)
downloadlinux-ef15e5490edc7edf808d3477ab32e0e320792f65.tar.xz
usb: gadget: ci13xxx: don't use "advance" feature when setting address
Newer versions of the chipidea controller support the "advance" setting of usb address, which means instead of setting it immediately, deferring it till the status completion. Unfortunately, older versions of the controller don't have this feature, so in order to support those too, we simply don't use it. It's about 4 lines of extra code, and isn't in any way critical to performance. While at it, change the return value of the hw_usb_set_address() to void, since it can't fail in any measurable way. With this patch, ci13xxx_udc driver works with the chipidea controller in kirkwood (feroceon SoC), as found in, for example, sheevaplug. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c22
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.h2
2 files changed, 14 insertions, 10 deletions
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 0c94fe7..6d2d654 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -722,14 +722,13 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
* hw_usb_set_address: configures USB address (execute without interruption)
* @value: new USB address
*
- * This function returns an error code
+ * This function explicitly sets the address, without the "USBADRA" (advance)
+ * feature, which is not supported by older versions of the controller.
*/
-static int hw_usb_set_address(struct ci13xxx *udc, u8 value)
+static void hw_usb_set_address(struct ci13xxx *udc, u8 value)
{
- /* advance */
- hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
- value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
- return 0;
+ hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR,
+ value << ffs_nr(DEVICEADDR_USBADR));
}
/**
@@ -1803,6 +1802,11 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
struct ci13xxx *udc = req->context;
unsigned long flags;
+ if (udc->setaddr) {
+ hw_usb_set_address(udc, udc->address);
+ udc->setaddr = false;
+ }
+
spin_lock_irqsave(&udc->lock, flags);
if (udc->test_mode)
hw_port_test_set(udc, udc->test_mode);
@@ -1990,10 +1994,8 @@ __acquires(udc->lock)
if (le16_to_cpu(req.wLength) != 0 ||
le16_to_cpu(req.wIndex) != 0)
break;
- err = hw_usb_set_address(udc,
- (u8)le16_to_cpu(req.wValue));
- if (err)
- break;
+ udc->address = (u8)le16_to_cpu(req.wValue);
+ udc->setaddr = true;
err = isr_setup_status_phase(udc);
break;
case USB_REQ_SET_FEATURE:
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index a4cad41..a8aa1a70 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -141,6 +141,8 @@ struct ci13xxx {
struct ci13xxx_ep *ep0out, *ep0in;
unsigned hw_ep_max; /* number of hw endpoints */
+ bool setaddr;
+ u8 address;
u8 remote_wakeup; /* Is remote wakeup feature
enabled by the host? */
u8 suspended; /* suspended by the host */