Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 184d6fd3 authored by Shimrit Malichi's avatar Shimrit Malichi Committed by Mayank Rana
Browse files

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: default avatarShimrit Malichi <smalichi@codeaurora.org>
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent b6cadaa8
Loading
Loading
Loading
Loading
+37 −30
Original line number Diff line number Diff line
@@ -711,7 +711,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++;
@@ -721,9 +722,10 @@ 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 | USB_BESL_SUPPORT);

	if (gadget_is_superspeed(cdev->gadget)) {
		/*
	 * The Superspeed USB Capability descriptor shall be implemented by all
	 * SuperSpeed devices.
		 * The Superspeed USB Capability descriptor shall be
		 * implemented by all SuperSpeed devices.
		 */
		ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
		bos->bNumDeviceCaps++;
@@ -740,14 +742,17 @@ static int bos_desc(struct usb_composite_dev *cdev)

		/* Get Controller configuration */
		if (cdev->gadget->ops->get_config_params)
		cdev->gadget->ops->get_config_params(&dcd_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.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;
	}

	/* The SuperSpeedPlus USB Device Capability descriptor */
	if (gadget_is_superspeed_plus(cdev->gadget)) {
@@ -1709,8 +1714,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);
@@ -1741,7 +1747,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);
			}