Skip to content

Commit

Permalink
usb: gadget: ci13xxx: don't use "advance" feature when setting address
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexander Shishkin authored and Greg Kroah-Hartman committed May 11, 2012
1 parent 405b844 commit ef15e54
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 10 deletions.
22 changes: 12 additions & 10 deletions drivers/usb/gadget/ci13xxx_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/**
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/gadget/ci13xxx_udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit ef15e54

Please sign in to comment.