summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hub.c95
-rw-r--r--drivers/usb/core/otg_whitelist.h68
-rw-r--r--drivers/usb/gadget/Kconfig11
-rw-r--r--drivers/usb/musb/musb_virthub.c2
4 files changed, 175 insertions, 1 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index abb0084795c..f4038c53b61 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3569,6 +3569,101 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (status)
dev_dbg(hub_dev, "%dmA power budget left\n", status);
+#ifdef CONFIG_USB_OTG_20
+
+ u16 idVendor = le16_to_cpu(udev->descriptor.idVendor);
+ if (idVendor == USB_OTG_TEST_MODE_VID) {
+ u16 wValue, typeReq, wIndex;
+ u32 set_feature = 0;
+ int err = 0;
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ u16 idProduct = le16_to_cpu(
+ udev->descriptor.idProduct);
+ /* Convert the Test Mode Request
+ * to control request
+ */
+ wValue = USB_PORT_FEAT_TEST;
+ typeReq = SetPortFeature;
+ wIndex = 1;
+
+ switch (idProduct) {
+ case USB_OTG_TEST_SE0_NAK_PID:
+ wIndex |= USB_OTG_TEST_SE0_NAK << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_J_PID:
+ wIndex |= USB_OTG_TEST_J << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_K_PID:
+ wIndex |= USB_OTG_TEST_K << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_PACKET_PID:
+ wIndex |= USB_OTG_TEST_PACKET << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_HS_HOST_PORT_SUSPEND_RESUME_PID:
+ /* Sleep for 15 sec. Suspend
+ * for 15 Sec, Then Resume
+ */
+ ssleep(15);
+
+ err = usb_port_suspend(udev,
+ PMSG_SUSPEND);
+ if (err < 0) {
+ dev_err(&udev->dev, "OTG TEST_MODE:"
+ "Suspend Fail, %d\n", err);
+ goto loop_disable;
+ }
+ ssleep(15);
+ err = usb_port_resume(udev, PMSG_RESUME);
+ if (err < 0) {
+ dev_err(&udev->dev,
+ "can't resume for"
+ "OTG TEST_MODE: %d\n", err);
+ goto loop_disable;
+ }
+ break;
+ case USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_PID:
+ /* Sleep for 15 Sec. Issue the GetDeviceDescriptor */
+ ssleep(15);
+ err = usb_get_device_descriptor(udev,
+ sizeof(udev->descriptor));
+ if (err < 0) {
+ dev_err(&udev->dev, "can't re-read"
+ "device descriptor for "
+ "OTG TEST MODE: %d\n", err);
+ goto loop_disable;
+ }
+ break;
+ case USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_DATA_PID:
+ /* Issue GetDeviceDescriptor, Sleep for 15 Sec. */
+ err = usb_get_device_descriptor(udev,
+ sizeof(udev->descriptor));
+ if (err < 0) {
+ dev_err(&udev->dev, "can't re-read"
+ "device descriptor for "
+ "OTG TEST MODE: %d\n", err);
+ goto loop_disable;
+ }
+ ssleep(15);
+ break;
+ default:
+ /* is_targeted() will take care for wrong PID */
+ dev_dbg(&udev->dev, "OTG TEST_MODE:Wrong
+ PID %d\n" idProduct);
+ break;
+ }
+
+ if (set_feature) {
+ err = hcd->driver->hub_control(hcd,
+ typeReq, wValue, wIndex,
+ NULL, 0);
+ }
+ }
+
+#endif
return;
loop_disable:
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index e8cdce571bb..86a09972836 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -43,12 +43,50 @@ static struct usb_device_id whitelist_table [] = {
{ USB_DEVICE(0x0525, 0xa4a0), },
#endif
+#ifdef CONFIG_USB_OTG_20
+{ USB_DEVICE_INFO(8, 6, 80) },/* Mass Storage Devices */
+{ USB_DEVICE_INFO(1, 1, 0) },/* Audio Devices */
+{ USB_DEVICE_INFO(3, 0, 0) },/* keyboard Devices */
+{ USB_DEVICE_INFO(3, 1, 2) },/* Mouse Devices */
+
+/* Test Devices */
+{ USB_DEVICE(0x1A0A, 0x0101), },/* Test_SE0_NAK */
+{ USB_DEVICE(0x1A0A, 0x0102), },/* Test_J */
+{ USB_DEVICE(0x1A0A, 0x0103), },/* Test_K */
+{ USB_DEVICE(0x1A0A, 0x0104), },/* Test_Packet */
+{ USB_DEVICE(0x1A0A, 0x0106), },/* HS_HOST_PORT_SUSPEND_RESUME */
+{ USB_DEVICE(0x1A0A, 0x0107), },/* SINGLE_STEP_GET_DEV_DESC */
+{ USB_DEVICE(0x1A0A, 0x0108), },/* SINGLE_STEP_ GET_DEV_DESC_DATA*/
+{ USB_DEVICE(0x1A0A, 0x0201), },/* OTG 2 TEST DEVICE*/
+#endif
{ } /* Terminating entry */
};
+/* The TEST_MODE Definition for OTG as per 6.4 of OTG Rev 2.0 */
+
+#ifdef CONFIG_USB_OTG_20
+#define USB_OTG_TEST_MODE_VID 0x1A0A
+#define USB_OTG_TEST_SE0_NAK_PID 0x0101
+#define USB_OTG_TEST_J_PID 0x0102
+#define USB_OTG_TEST_K_PID 0x0103
+#define USB_OTG_TEST_PACKET_PID 0x0104
+#define USB_OTG_TEST_HS_HOST_PORT_SUSPEND_RESUME_PID 0x0106
+#define USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_PID 0x0107
+#define USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_DATA_PID 0x0108
+
+#define USB_OTG_TEST_SE0_NAK 0x01
+#define USB_OTG_TEST_J 0x02
+#define USB_OTG_TEST_K 0x03
+#define USB_OTG_TEST_PACKET 0x04
+#endif
+
static int is_targeted(struct usb_device *dev)
{
struct usb_device_id *id = whitelist_table;
+#ifdef CONFIG_USB_OTG_20
+ u8 number_configs = 0;
+ u8 number_interface = 0;
+#endif
/* possible in developer configs only! */
if (!dev->bus->otg_port)
@@ -98,6 +136,36 @@ static int is_targeted(struct usb_device *dev)
/* add other match criteria here ... */
+#ifdef CONFIG_USB_OTG_20
+
+ /* Checking class,subclass and protocal at interface level */
+ for (number_configs = dev->descriptor.bNumConfigurations;
+ number_configs > 0; number_configs--)
+ for (number_interface = dev->config->desc.bNumInterfaces;
+ number_interface > 0;
+ number_interface--)
+ for (id = whitelist_table; id->match_flags; id++) {
+ if ((id->match_flags &
+ USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+ (id->bDeviceClass !=
+ dev->config->intf_cache[number_interface-1]
+ ->altsetting[0].desc.bInterfaceClass))
+ continue;
+ if ((id->match_flags &
+ USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
+ && (id->bDeviceSubClass !=
+ dev->config->intf_cache[number_interface-1]
+ ->altsetting[0].desc.bInterfaceSubClass))
+ continue;
+ if ((id->match_flags &
+ USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+ && (id->bDeviceProtocol !=
+ dev->config->intf_cache[number_interface-1]
+ ->altsetting[0].desc.bInterfaceProtocol))
+ continue;
+ return 1;
+ }
+#endif
/* OTG MESSAGE: report errors here, customize to match your product */
dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2633f759511..7e99677b81b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -977,4 +977,15 @@ config USB_G_WEBCAM
endchoice
+config USB_OTG_20
+ bool "OTG 2.0 USB SUPPORT"
+ select USB_OTG
+ select PM_RUNTIME
+ select USB_OTG_WHITELIST
+ select USB_SUSPEND
+ default n
+ help
+ Enabling the whitelist (Target Peripheral List-TPL) and runtime power
+ management at system level and usb level for OTG 2.0.
+
endif # USB_GADGET
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 22ec3e37998..702d5efe9ef 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -379,7 +379,7 @@ int musb_hub_control(
musb_port_suspend(musb, true);
break;
case USB_PORT_FEAT_TEST:
- if (unlikely(is_host_active(musb)))
+ if (unlikely(!is_host_active(musb)))
goto error;
wIndex >>= 8;