summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */
OpenPOWER on IntegriCloud