@@ -419,6 +419,45 @@ struct dwc3_glue_ops rk_ops = {
.glue_get_ctrl_dev = dwc3_rk_glue_get_ctrl_dev,
};
+static void dwc3_hi3798mv200_glue_configure(struct udevice *dev, ofnode child, int index)
+{
+#define HI3798MV200_PERI_CTRL_ADDR 0xf8a20000
+#define HI3798MV200_PERI_USB5 0x134
+#define USB3_U3_PORT_DISABLE BIT(5)
+#define USB3_U2_PORT_DISABLE BIT(4)
+
+ // Disable super-speed port if maximum speed is high-speed
+ void __iomem *peri_base = map_physmem(HI3798MV200_PERI_CTRL_ADDR, 0x1000, MAP_NOCACHE);
+ enum usb_device_speed speed = usb_get_maximum_speed(child);
+ u32 reg;
+
+ reg = readl(peri_base + HI3798MV200_PERI_USB5);
+ reg &= ~(USB3_U3_PORT_DISABLE | USB3_U2_PORT_DISABLE);
+
+ switch (speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ case USB_SPEED_HIGH:
+ // disable super-speed port
+ reg |= USB3_U3_PORT_DISABLE;
+ pr_info("%s: super-speed port disabled.\n", __func__);
+ break;
+
+ case USB_SPEED_SUPER:
+ break;
+
+ default:
+ pr_warn("%s: unknown speed class %d.\n", __func__, speed);
+ }
+
+ writel(reg, peri_base + HI3798MV200_PERI_USB5);
+ unmap_physmem(peri_base, MAP_NOCACHE);
+}
+
+const struct dwc3_glue_ops hi3798mv200_ops = {
+ .glue_configure = dwc3_hi3798mv200_glue_configure,
+};
+
static int dwc3_glue_bind_common(struct udevice *parent, ofnode node)
{
const char *name = ofnode_get_name(node);
@@ -611,6 +650,7 @@ static const struct udevice_id dwc3_glue_ids[] = {
{ .compatible = "fsl,imx8mp-dwc3", .data = (ulong)&imx8mp_ops },
{ .compatible = "fsl,imx8mq-dwc3" },
{ .compatible = "intel,tangier-dwc3" },
+ { .compatible = "hisilicon,hi3798mv200-dwc3", .data = (ulong)&hi3798mv200_ops },
{ }
};