[PATCH 0/3] usb: dwv3: add glue driver for hi3798mv200

Also edit the prototype of .glue_configure to fulfill our needs.
Signed-off-by: Yang Xiwen forbidden405@outlook.com --- Yang Xiwen (3): usb: dwc3: handle return value of clk_get_rate() correctly usb: dwc3: replace argument mode with child ofnode usb: dwc3: add glue driver for Hi3798MV200
drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/dwc3-generic.c | 52 ++++++++++++++++++++++++++++++++++------- drivers/usb/dwc3/dwc3-generic.h | 3 +-- 3 files changed, 46 insertions(+), 11 deletions(-) --- base-commit: 050a9b981d6a835133521b599be3ae189ce70f41 change-id: 20240203-hisi-dwc3-3c47f734cd20
Best regards,

From: Yang Xiwen forbidden405@outlook.com
clk_get_rate() return -ve on error, not 0. Fix it by replacing judging NULL with IS_ERR_VALUE().
Fixes: 6bae0eb5b8bd("usb: dwc3: Calculate REFCLKPER based on reference clock") Signed-off-by: Yang Xiwen forbidden405@outlook.com --- drivers/usb/dwc3/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 4b4fcd8a22..06ff68105e 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -137,7 +137,7 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc)
if (dwc->ref_clk) { rate = clk_get_rate(dwc->ref_clk); - if (!rate) + if (IS_ERR_VALUE(rate)) return; period = NSEC_PER_SEC / rate; } else {

On Sat, Feb 03, 2024 at 07:01:54AM +0800, Yang Xiwen via B4 Relay wrote:
From: Yang Xiwen forbidden405@outlook.com
clk_get_rate() return -ve on error, not 0. Fix it by replacing judging NULL with IS_ERR_VALUE().
^^^^
s/NULL/zero/.
I'd be surprised if clk_get_rate() *never* returns zero. The Linux kernel's clk_get_rate() function returns zero and not error codes, btw.
regards, dan carpenter

On 2/5/2024 3:25 PM, Dan Carpenter wrote:
On Sat, Feb 03, 2024 at 07:01:54AM +0800, Yang Xiwen via B4 Relay wrote:
From: Yang Xiwen forbidden405@outlook.com
clk_get_rate() return -ve on error, not 0. Fix it by replacing judging NULL with IS_ERR_VALUE().
^^^^
s/NULL/zero/.
I'd be surprised if clk_get_rate() *never* returns zero. The Linux kernel's clk_get_rate() function returns zero and not error codes, btw.
Yes, it's really surprising. U-Boot clk APIs are a little different from Linux kernel's. Sadly it's a bit too late to fix it since there are really plenty of existing users. Maybe we need to put some hints in the docs.
regards, dan carpenter

From: Yang Xiwen forbidden405@outlook.com
child ofnode is more useful and can be used to query a lot of other props of child device. dr_mode can be also queried from it.
Signed-off-by: Yang Xiwen forbidden405@outlook.com --- drivers/usb/dwc3/dwc3-generic.c | 12 ++++-------- drivers/usb/dwc3/dwc3-generic.h | 3 +-- 2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 6fb2de8a5a..d892042b91 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -272,8 +272,7 @@ U_BOOT_DRIVER(dwc3_generic_host) = { }; #endif
-void dwc3_imx8mp_glue_configure(struct udevice *dev, int index, - enum usb_dr_mode mode) +void dwc3_imx8mp_glue_configure(struct udevice *dev, ofnode child, int index) { /* USB glue registers */ #define USB_CTRL0 0x00 @@ -323,8 +322,7 @@ struct dwc3_glue_ops imx8mp_ops = { .glue_configure = dwc3_imx8mp_glue_configure, };
-void dwc3_ti_glue_configure(struct udevice *dev, int index, - enum usb_dr_mode mode) +void dwc3_ti_glue_configure(struct udevice *dev, ofnode child, int index) { #define USBOTGSS_UTMI_OTG_STATUS 0x0084 #define USBOTGSS_UTMI_OTG_OFFSET 0x0480 @@ -348,6 +346,7 @@ enum dwc3_omap_utmi_mode { u32 reg; u32 utmi_mode; u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS; + enum usb_dr_mode mode = usb_get_dr_mode(child);
struct dwc3_glue_data *glue = dev_get_plat(dev); void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE); @@ -577,12 +576,9 @@ int dwc3_glue_probe(struct udevice *dev) }
while (child) { - enum usb_dr_mode dr_mode; - - dr_mode = usb_get_dr_mode(dev_ofnode(child)); device_find_next_child(&child); if (ops && ops->glue_configure) - ops->glue_configure(dev, index, dr_mode); + ops->glue_configure(dev, dev_ofnode(child), index); index++; }
diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h index 40902c8923..46c14a338b 100644 --- a/drivers/usb/dwc3/dwc3-generic.h +++ b/drivers/usb/dwc3/dwc3-generic.h @@ -22,8 +22,7 @@ struct dwc3_glue_data {
struct dwc3_glue_ops { int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node); - void (*glue_configure)(struct udevice *dev, int index, - enum usb_dr_mode mode); + void (*glue_configure)(struct udevice *parent, ofnode node, int index); };
int dwc3_glue_bind(struct udevice *parent);

From: Yang Xiwen forbidden405@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 forbidden405@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 }, { } };
participants (3)
-
Dan Carpenter
-
Yang Xiwen
-
Yang Xiwen via B4 Relay