[PATCH v4 13/24] usb: gadget: ci13xxx: don't use "advance" feature when setting address

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

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@xxxxxxxxxxxxxxx>
---
 drivers/usb/gadget/ci13xxx_udc.c |   22 ++++++++++++----------
 drivers/usb/gadget/ci13xxx_udc.h |    1 +
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 8802906..1da415f 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));
 }
 
 /**
@@ -1831,6 +1830,11 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
 
 	trace(udc->dev, "%s, %p", ep->name, req);
 
+	if (udc->addr_to_set) {
+		hw_usb_set_address(udc, udc->addr_to_set);
+		udc->addr_to_set = 0;
+	}
+
 	spin_lock_irqsave(&udc->lock, flags);
 	if (udc->test_mode)
 		hw_port_test_set(udc, udc->test_mode);
@@ -2024,10 +2028,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;
+			/* defer the address setting XXX */
+			udc->addr_to_set = (u8)le16_to_cpu(req.wValue);
 			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 1bfab4b..a84dffb 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -142,6 +142,7 @@ struct ci13xxx {
 	struct ci13xxx_ep          *ep0out, *ep0in;
 	unsigned		   hw_ep_max;  /* number of hw endpoints */
 
+	u8			   addr_to_set;
 	u8                         remote_wakeup; /* Is remote wakeup feature
 							enabled by the host? */
 	u8                         suspended;  /* suspended by the host */
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux