usb: gadget: Add link power management support
Link Power Management (a.k.a. L1) is similar to the existing usb bus suspend/resume/remote-wakeup, but has transitional latencies of tens of microseconds between power states (instead of three to greater than 20 millisecond latencies of the USB 2.0 suspend/resume). Change-Id: I8ae493534702e658c24f384a6b705b08e9ea9d05 Signed-off-by: Shimrit Malichi <smalichi@codeaurora.org> Signed-off-by: Tarun Gupta <tarung@codeaurora.org>
This commit is contained in:
parent
f67850e9f0
commit
37648e8eb6
2 changed files with 37 additions and 29 deletions
|
@ -653,7 +653,8 @@ static int bos_desc(struct usb_composite_dev *cdev)
|
|||
|
||||
/*
|
||||
* A SuperSpeed device shall include the USB2.0 extension descriptor
|
||||
* and shall support LPM when operating in USB2.0 HS mode.
|
||||
* and shall support LPM when operating in USB2.0 HS mode, as well as
|
||||
* a HS device when operating in USB2.1 HS mode.
|
||||
*/
|
||||
usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
|
||||
bos->bNumDeviceCaps++;
|
||||
|
@ -663,33 +664,37 @@ static int bos_desc(struct usb_composite_dev *cdev)
|
|||
usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
|
||||
usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
|
||||
|
||||
/*
|
||||
* The Superspeed USB Capability descriptor shall be implemented by all
|
||||
* SuperSpeed devices.
|
||||
*/
|
||||
ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
|
||||
bos->bNumDeviceCaps++;
|
||||
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
|
||||
ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
|
||||
ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
|
||||
ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
|
||||
ss_cap->bmAttributes = 0; /* LTM is not supported yet */
|
||||
ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
|
||||
USB_FULL_SPEED_OPERATION |
|
||||
USB_HIGH_SPEED_OPERATION |
|
||||
USB_5GBPS_OPERATION);
|
||||
ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
|
||||
if (gadget_is_superspeed(cdev->gadget)) {
|
||||
/*
|
||||
* The Superspeed USB Capability descriptor shall be
|
||||
* implemented by all SuperSpeed devices.
|
||||
*/
|
||||
ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
|
||||
bos->bNumDeviceCaps++;
|
||||
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
|
||||
ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
|
||||
ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
|
||||
ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
|
||||
ss_cap->bmAttributes = 0; /* LTM is not supported yet */
|
||||
ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
|
||||
USB_FULL_SPEED_OPERATION |
|
||||
USB_HIGH_SPEED_OPERATION |
|
||||
USB_5GBPS_OPERATION);
|
||||
ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
|
||||
|
||||
/* Get Controller configuration */
|
||||
if (cdev->gadget->ops->get_config_params)
|
||||
cdev->gadget->ops->get_config_params(&dcd_config_params);
|
||||
else {
|
||||
dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
|
||||
dcd_config_params.bU2DevExitLat =
|
||||
cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
|
||||
/* Get Controller configuration */
|
||||
if (cdev->gadget->ops->get_config_params)
|
||||
cdev->gadget->ops->get_config_params
|
||||
(&dcd_config_params);
|
||||
else {
|
||||
dcd_config_params.bU1devExitLat =
|
||||
USB_DEFAULT_U1_DEV_EXIT_LAT;
|
||||
dcd_config_params.bU2DevExitLat =
|
||||
cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
|
||||
}
|
||||
ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
|
||||
ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
|
||||
}
|
||||
ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
|
||||
ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
|
||||
|
||||
return le16_to_cpu(bos->wTotalLength);
|
||||
}
|
||||
|
@ -1623,8 +1628,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
} else {
|
||||
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
|
||||
}
|
||||
} else {
|
||||
cdev->desc.bcdUSB = cpu_to_le16(0x0200);
|
||||
} else if (gadget->l1_supported) {
|
||||
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
|
||||
DBG(cdev, "Config HS device with LPM(L1)\n");
|
||||
}
|
||||
|
||||
value = min(w_length, (u16) sizeof cdev->desc);
|
||||
|
@ -1655,7 +1661,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
value = min(w_length, (u16) value);
|
||||
break;
|
||||
case USB_DT_BOS:
|
||||
if (gadget_is_superspeed(gadget)) {
|
||||
if (gadget_is_superspeed(gadget) ||
|
||||
gadget->l1_supported) {
|
||||
value = bos_desc(cdev);
|
||||
value = min(w_length, (u16) value);
|
||||
}
|
||||
|
|
|
@ -647,6 +647,7 @@ struct usb_gadget {
|
|||
unsigned is_selfpowered:1;
|
||||
unsigned deactivated:1;
|
||||
unsigned connected:1;
|
||||
bool l1_supported;
|
||||
};
|
||||
#define work_to_gadget(w) (container_of((w), struct usb_gadget, work))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue