diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 1efc53bfcc80b7d7ce2c42cfe65cdb0204b06f68..7bb23edf5b7c6ba6bc8d0637b99d4d212f5c9a20 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -218,6 +218,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_VIA)
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
+	if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
+		xhci->quirks |= XHCI_LPM_SUPPORT;
+		xhci->quirks |= XHCI_ZHAOXIN_HOST;
+	}
 
 	/* See https://bugzilla.kernel.org/show_bug.cgi?id=79511 */
 	if (pdev->vendor == PCI_VENDOR_ID_VIA &&
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index faa76c3fa15d6e2eda901d1bf26f9521d042947d..918aeca9e789a2d0d9d3014a2476c48f91d60704 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4554,7 +4554,7 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
 		}
 	}
 
-	if (xhci->quirks & XHCI_INTEL_HOST)
+	if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST))
 		timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
 	else
 		timeout_ns = udev->u1_params.sel;
@@ -4618,7 +4618,7 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
 		}
 	}
 
-	if (xhci->quirks & XHCI_INTEL_HOST)
+	if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST))
 		timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
 	else
 		timeout_ns = udev->u2_params.sel;
@@ -4715,12 +4715,42 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev,
 	return -E2BIG;
 }
 
+static int xhci_check_zhaoxin_tier_policy(struct usb_device *udev,
+							enum usb3_link_state state)
+{
+	struct usb_device *parent;
+	unsigned int num_hubs;
+	char *state_name;
+
+	if (state == USB3_LPM_U1)
+		state_name = "U1";
+	else if (state == USB3_LPM_U2)
+		state_name = "U2";
+	else
+		state_name = "Unknown";
+	/* Don't enable U1/U2 if the device is on an external hub*/
+	for (parent = udev->parent, num_hubs = 0; parent->parent;
+			parent = parent->parent)
+			num_hubs++;
+
+	if (num_hubs < 1)
+		return 0;
+
+	dev_dbg(&udev->dev, "Disabling %s link state for device" \
+							" below external hub.\n", state_name);
+	dev_dbg(&udev->dev, "Plug device into root port " \
+							"to decrease power consumption.\n");
+	return -E2BIG;
+}
+
 static int xhci_check_tier_policy(struct xhci_hcd *xhci,
 		struct usb_device *udev,
 		enum usb3_link_state state)
 {
 	if (xhci->quirks & XHCI_INTEL_HOST)
 		return xhci_check_intel_tier_policy(udev, state);
+	else if (xhci->quirks & XHCI_ZHAOXIN_HOST)
+		return xhci_check_zhaoxin_tier_policy(udev, state);
 	else
 		return 0;
 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 4dedc822237fca0eac32d14e5f1818eb80e44fd6..b02911887d209b846c66a91302446db766a3433a 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1872,6 +1872,7 @@ struct xhci_hcd {
 #define XHCI_ZERO_64B_REGS	BIT_ULL(32)
 #define XHCI_RESET_PLL_ON_DISCONNECT	BIT_ULL(34)
 #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
+#define XHCI_ZHAOXIN_HOST       BIT_ULL(36)
 
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;