From: Yang Xiwen <forbidden...@outlook.com>

It needs some platform-specific operations before generic initialization
code.

If nano PHY is not initialized properly, it must be disabled. Or else
 USB host will complain unable to reset port.

USB2 is always supported, so it's never disabled.

Signed-off-by: Yang Xiwen <forbidden...@outlook.com>
---
 drivers/usb/dwc3/dwc3-generic.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index d892042b91..a3200ff1ab 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -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 },
        { }
 };
 

-- 
2.43.0

Reply via email to