summaryrefslogtreecommitdiffstats
path: root/drivers/usb/common
diff options
context:
space:
mode:
authorChunfeng Yun <chunfeng.yun@mediatek.com>2021-03-08 10:52:05 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-10 09:37:17 +0100
commitfb95c7cf5600b7b74412f27dfb39a1e13fd8a90d (patch)
treea26adef0d2e1159293afa37941a1970bd206d2a5 /drivers/usb/common
parent14295a150050acfc3a1260ee3d2114b0b824199f (diff)
downloadlinux-fb95c7cf5600b7b74412f27dfb39a1e13fd8a90d.tar.bz2
usb: common: add function to get interval expressed in us unit
Add a new function to convert bInterval into the time expressed in 1us unit. Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> Link: https://lore.kernel.org/r/25c8a09b055f716c1e5bf11fea72c3418f844482.1615170625.git.chunfeng.yun@mediatek.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/common')
-rw-r--r--drivers/usb/common/common.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index fc21cf2d36f6..675e8a4e683a 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -165,6 +165,47 @@ enum usb_dr_mode usb_get_dr_mode(struct device *dev)
}
EXPORT_SYMBOL_GPL(usb_get_dr_mode);
+/**
+ * usb_decode_interval - Decode bInterval into the time expressed in 1us unit
+ * @epd: The descriptor of the endpoint
+ * @speed: The speed that the endpoint works as
+ *
+ * Function returns the interval expressed in 1us unit for servicing
+ * endpoint for data transfers.
+ */
+unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd,
+ enum usb_device_speed speed)
+{
+ unsigned int interval = 0;
+
+ switch (usb_endpoint_type(epd)) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* uframes per NAK */
+ if (speed == USB_SPEED_HIGH)
+ interval = epd->bInterval;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ interval = 1 << (epd->bInterval - 1);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ /* uframes per NAK */
+ if (speed == USB_SPEED_HIGH && usb_endpoint_dir_out(epd))
+ interval = epd->bInterval;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (speed >= USB_SPEED_HIGH)
+ interval = 1 << (epd->bInterval - 1);
+ else
+ interval = epd->bInterval;
+ break;
+ }
+
+ interval *= (speed >= USB_SPEED_HIGH) ? 125 : 1000;
+
+ return interval;
+}
+EXPORT_SYMBOL_GPL(usb_decode_interval);
+
#ifdef CONFIG_OF
/**
* of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device