diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 0bae1beea8a6..d09e968644c1 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1297,6 +1297,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 				"snps,usb3_lpm_capable");
 	dwc->usb2_lpm_disable = device_property_read_bool(dev,
 				"snps,usb2-lpm-disable");
+	device_property_read_u8(dev, "snps,maximum-lane-count",
+				&dwc->maximum_lanes);
+	device_property_read_u8(dev, "snps,maximum-lsm",
+				&dwc->maximum_lsm);
 	device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd",
 				&rx_thr_num_pkt_prd);
 	device_property_read_u8(dev, "snps,rx-max-burst-prd",
@@ -1424,6 +1428,38 @@ static void dwc3_check_params(struct dwc3 *dwc)
 
 		break;
 	}
+
+	switch (dwc->maximum_lsm) {
+	case 5:
+		break;
+	case 10:
+		if (dwc->maximum_speed == USB_SPEED_SUPER)
+			dev_err(dev, "invalid maximum_lsm parameter %d\n",
+				dwc->maximum_lsm);
+		/* Fall Through */
+	default:
+		if (dwc->maximum_speed == USB_SPEED_SUPER)
+			dwc->maximum_lsm = 5;
+		else if (dwc->maximum_speed > USB_SPEED_SUPER)
+			dwc->maximum_lsm = 10;
+		break;
+	}
+
+	switch (dwc->maximum_lanes) {
+	case 1:
+	case 2:
+		break;
+	default:
+		if (dwc->maximum_lanes > 2)
+			dev_err(dev, "invalid number of lanes %d\n",
+				dwc->maximum_lanes);
+
+		if (dwc3_is_usb32(dwc) &&
+		    dwc->maximum_speed == USB_SPEED_SUPER_PLUS)
+			dwc->maximum_lanes = 2;
+		else
+			dwc->maximum_lanes = 1;
+	}
 }
 
 static int dwc3_probe(struct platform_device *pdev)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 7fde3c7da543..8e729d4cd5bd 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -376,6 +376,8 @@
 #define DWC3_GUCTL2_RST_ACTBITLATER		BIT(14)
 
 /* Device Configuration Register */
+#define DWC3_DCFG_NUMLANES(n)	(((n) & 0x3) << 30) /* DWC_usb32 only */
+
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
 
@@ -449,6 +451,8 @@
 #define DWC3_DEVTEN_USBRSTEN		BIT(1)
 #define DWC3_DEVTEN_DISCONNEVTEN	BIT(0)
 
+#define DWC3_DSTS_CONNLANES(n)		(((n) >> 30) & 0x3) /* DWC_usb32 only */
+
 /* Device Status Register */
 #define DWC3_DSTS_DCNRD			BIT(29)
 
@@ -946,6 +950,8 @@ struct dwc3_scratchpad_array {
  * @nr_scratch: number of scratch buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
+ * @maximum_lsm: maximum lane speed mantissa in Gbps
+ * @maximum_lanes: maximum lane count
  * @ip: controller's ID
  * @revision: controller's version of an IP
  * @version_type: VERSIONTYPE register contents, a sub release of a revision
@@ -973,6 +979,7 @@ struct dwc3_scratchpad_array {
  * @ep0state: state of endpoint zero
  * @link_state: link state
  * @speed: device speed (super, high, full, low)
+ * @lane_count: number of connected lanes
  * @hwparams: copy of hwparams registers
  * @root: debugfs root folder pointer
  * @regset: debugfs pointer to regdump file
@@ -1100,6 +1107,8 @@ struct dwc3 {
 	u32			nr_scratch;
 	u32			u1u2;
 	u32			maximum_speed;
+	u8			maximum_lsm;
+	u8			maximum_lanes;
 
 	u32			ip;
 
@@ -1159,6 +1168,7 @@ struct dwc3 {
 	u8			u1pel;
 
 	u8			speed;
+	u8			lane_count;
 
 	u8			num_eps;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a6d562e208a9..c31144af3261 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2183,6 +2183,53 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
 	spin_unlock_irqrestore(&dwc->lock, flags);
 }
 
+static void dwc3_gadget_set_sublink_attr(struct usb_gadget *g,
+					 unsigned int lane_count,
+					 unsigned int lsm)
+{
+	struct dwc3	*dwc = gadget_to_dwc(g);
+	unsigned int	lanes;
+	unsigned long	flags;
+	u32		reg;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	if (dwc->maximum_speed <= USB_SPEED_SUPER) {
+		/* Fall back to maximum speed supported by HW */
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		dwc3_gadget_set_speed(g, dwc->maximum_speed);
+		spin_lock_irqsave(&dwc->lock, flags);
+
+		goto done;
+	}
+
+	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+	reg &= ~DWC3_DCFG_SPEED_MASK;
+
+	switch (lsm) {
+	case 5:
+		reg |= DWC3_DCFG_SUPERSPEED;
+		break;
+	case 10:
+		reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+		break;
+	default:
+		dev_err(dwc->dev, "invalid lane speed mantissa (%d)\n", lsm);
+		goto done;
+	}
+
+	/* Lane configuration is only available to dwc_usb32 and higher */
+	if (dwc3_is_usb32(dwc)) {
+		lanes = clamp_t(unsigned int, lane_count,
+				1, dwc->maximum_lanes);
+		reg &= ~DWC3_DCFG_NUMLANES(3);
+		reg |= DWC3_DCFG_NUMLANES(lanes - 1);
+	}
+
+	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+done:
+	spin_unlock_irqrestore(&dwc->lock, flags);
+}
+
 static const struct usb_gadget_ops dwc3_gadget_ops = {
 	.get_frame		= dwc3_gadget_get_frame,
 	.wakeup			= dwc3_gadget_wakeup,
@@ -2191,6 +2238,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 	.udc_start		= dwc3_gadget_start,
 	.udc_stop		= dwc3_gadget_stop,
 	.udc_set_speed		= dwc3_gadget_set_speed,
+	.udc_set_sublink_attr	= dwc3_gadget_set_sublink_attr,
 	.get_config_params	= dwc3_gadget_config_params,
 };
 
@@ -3383,6 +3431,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	dwc->gadget.sg_supported	= true;
 	dwc->gadget.name		= "dwc3-gadget";
 	dwc->gadget.lpm_capable		= true;
+	dwc->gadget.lane_count		= 1;
 
 	/*
 	 * FIXME We might be setting max_speed to <SUPER, however versions
@@ -3406,6 +3455,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 				dwc->revision);
 
 	dwc->gadget.max_speed		= dwc->maximum_speed;
+	dwc->gadget.max_lsm		= dwc->maximum_lsm;
+	dwc->gadget.max_lane_count	= dwc->maximum_lanes;
 
 	/*
 	 * REVISIT: Here we should clear all pending IRQs to be
@@ -3422,7 +3473,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 		goto err4;
 	}
 
-	dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
+	if (dwc3_is_usb32(dwc) && dwc->maximum_lsm)
+		dwc3_gadget_set_sublink_attr(&dwc->gadget,
+					     dwc->maximum_lanes,
+					     dwc->maximum_lsm);
+	else
+		dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
 
 	return 0;
 
