From fef8c84b57fd305205a13984530e81af6bf81ac3 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 7 Apr 2025 11:54:21 +0200 Subject: usb: host: ehci-msm: Fix pointer check dev_read_addr_ptr() returns a null pointer on error, not FDT_ADDR_T_NONE. Fixes: 2be1130a9305 ("usb: ehci-msm: Use dev interface to get device address") Signed-off-by: Stephan Gerhold Acked-by: Caleb Connolly Tested-by: Sam Day Link: https://patch.msgid.link/20250407-ehci-msm-fixes-v1-1-f8b30eb05d07@linaro.org Signed-off-by: Casey Connolly --- drivers/usb/host/ehci-msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index a759aea9db3..dd1d527a3a2 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -141,7 +141,7 @@ static int ehci_usb_of_to_plat(struct udevice *dev) priv->ulpi_vp.port_num = 0; priv->ehci = dev_read_addr_ptr(dev); - if (priv->ehci == (void *)FDT_ADDR_T_NONE) + if (!priv->ehci) return -EINVAL; /* Warning: this will not work if viewport address is > 64 bit due to -- cgit v1.2.3 From e4e47da7e876d9f184e0060e6e59ac1f57d0290d Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 7 Apr 2025 11:54:22 +0200 Subject: usb: host: echi-msm: Drop ulpi definitions These are unused. Signed-off-by: Stephan Gerhold Acked-by: Caleb Connolly Tested-by: Sam Day Link: https://patch.msgid.link/20250407-ehci-msm-fixes-v1-2-f8b30eb05d07@linaro.org Signed-off-by: Casey Connolly --- drivers/usb/host/ehci-msm.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index dd1d527a3a2..60b2dc44d3d 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -24,7 +24,6 @@ struct msm_ehci_priv { struct ehci_ctrl ctrl; /* Needed by EHCI */ struct usb_ehci *ehci; /* Start of IP core*/ - struct ulpi_viewport ulpi_vp; /* ULPI Viewport */ struct phy phy; struct clk iface_clk; struct clk core_clk; @@ -138,17 +137,11 @@ static int ehci_usb_of_to_plat(struct udevice *dev) { struct msm_ehci_priv *priv = dev_get_priv(dev); - priv->ulpi_vp.port_num = 0; priv->ehci = dev_read_addr_ptr(dev); if (!priv->ehci) return -EINVAL; - /* Warning: this will not work if viewport address is > 64 bit due to - * ULPI design. - */ - priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint; - return 0; } -- cgit v1.2.3 From 2faabff35899a2106dc0480bd482783e906c8b7d Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 7 Apr 2025 11:54:23 +0200 Subject: usb: host: ehci-msm: Disable clocks after all register accesses We need the USB clocks to do accesses like wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, ...) so we should disable them only after all of them are done. At the moment this works only because the clock driver doesn't actually disabling these clocks in U-Boot. Fixes: 9b3a9f896e66 ("ehci: msm: bring up iface + core clocks") Signed-off-by: Stephan Gerhold Acked-by: Caleb Connolly Tested-by: Sam Day Link: https://patch.msgid.link/20250407-ehci-msm-fixes-v1-3-f8b30eb05d07@linaro.org Signed-off-by: Casey Connolly --- drivers/usb/host/ehci-msm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 60b2dc44d3d..bf46e89104e 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -110,9 +110,6 @@ static int ehci_usb_remove(struct udevice *dev) /* Stop controller. */ clrbits_le32(&ehci->usbcmd, CMD_RUN); - clk_disable_unprepare(&p->iface_clk); - clk_disable_unprepare(&p->core_clk); - ret = generic_shutdown_phy(&p->phy); if (ret) return ret; @@ -130,6 +127,8 @@ static int ehci_usb_remove(struct udevice *dev) return -ETIMEDOUT; } + clk_disable_unprepare(&p->iface_clk); + clk_disable_unprepare(&p->core_clk); return 0; } -- cgit v1.2.3 From c45a043d8a0e1589b09ce4d630b9d6bf41cb6755 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 7 Apr 2025 11:54:24 +0200 Subject: usb: host: ehci-msm: Use clk bulk helpers The enable order for the clocks does not matter much, we just need to enable all the USB clocks. Use the clk bulk helpers to simplify the code. Signed-off-by: Stephan Gerhold Acked-by: Caleb Connolly Tested-by: Sam Day Link: https://patch.msgid.link/20250407-ehci-msm-fixes-v1-4-f8b30eb05d07@linaro.org Signed-off-by: Casey Connolly --- drivers/usb/host/ehci-msm.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index bf46e89104e..17cfff8380c 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -25,8 +25,7 @@ struct msm_ehci_priv { struct ehci_ctrl ctrl; /* Needed by EHCI */ struct usb_ehci *ehci; /* Start of IP core*/ struct phy phy; - struct clk iface_clk; - struct clk core_clk; + struct clk_bulk clks; }; static int msm_init_after_reset(struct ehci_ctrl *dev) @@ -55,25 +54,15 @@ static int ehci_usb_probe(struct udevice *dev) struct ehci_hcor *hcor; int ret; - ret = clk_get_by_name(dev, "core", &p->core_clk); - if (ret) { - dev_err(dev, "Failed to get core clock: %d\n", ret); + ret = clk_get_bulk(dev, &p->clks); + if (ret && (ret != -ENOSYS && ret != -ENOENT)) { + dev_err(dev, "Failed to get clocks: %d\n", ret); return ret; } - ret = clk_get_by_name(dev, "iface", &p->iface_clk); - if (ret) { - dev_err(dev, "Failed to get iface clock: %d\n", ret); - return ret; - } - - ret = clk_prepare_enable(&p->core_clk); - if (ret) - return ret; - - ret = clk_prepare_enable(&p->iface_clk); + ret = clk_enable_bulk(&p->clks); if (ret) - goto cleanup_core; + goto cleanup_clocks; hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength); hcor = (struct ehci_hcor *)((phys_addr_t)hccr + @@ -81,19 +70,17 @@ static int ehci_usb_probe(struct udevice *dev) ret = generic_setup_phy(dev, &p->phy, 0, PHY_MODE_USB_HOST, 0); if (ret) - goto cleanup_iface; + goto cleanup_clocks; ret = board_usb_init(0, plat->init_type); if (ret < 0) - goto cleanup_iface; + goto cleanup_clocks; return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0, plat->init_type); -cleanup_iface: - clk_disable_unprepare(&p->iface_clk); -cleanup_core: - clk_disable_unprepare(&p->core_clk); +cleanup_clocks: + clk_release_bulk(&p->clks); return ret; } @@ -127,8 +114,7 @@ static int ehci_usb_remove(struct udevice *dev) return -ETIMEDOUT; } - clk_disable_unprepare(&p->iface_clk); - clk_disable_unprepare(&p->core_clk); + clk_release_bulk(&p->clks); return 0; } -- cgit v1.2.3 From f5ff016b44902591520f020c77fd08e8de6fc412 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 7 Apr 2025 11:54:25 +0200 Subject: usb: host: ehci-msm: Drop redundant EHCI register writes ehci_unregister() already clears the CMD_RUN bit with more careful checks. It also ensures that we only do this in case we were actually in USB host (rather than USB device) mode. It's not clear what the extra register writes in the Qualcomm-specific ehci-msm driver are supposed to do, so just drop them. Signed-off-by: Stephan Gerhold Acked-by: Caleb Connolly Tested-by: Sam Day Link: https://patch.msgid.link/20250407-ehci-msm-fixes-v1-5-f8b30eb05d07@linaro.org Signed-off-by: Casey Connolly --- drivers/usb/host/ehci-msm.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 17cfff8380c..659a917ad27 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -87,16 +87,12 @@ cleanup_clocks: static int ehci_usb_remove(struct udevice *dev) { struct msm_ehci_priv *p = dev_get_priv(dev); - struct usb_ehci *ehci = p->ehci; int ret; ret = ehci_deregister(dev); if (ret) return ret; - /* Stop controller. */ - clrbits_le32(&ehci->usbcmd, CMD_RUN); - ret = generic_shutdown_phy(&p->phy); if (ret) return ret; @@ -105,15 +101,6 @@ static int ehci_usb_remove(struct udevice *dev) if (ret < 0) return ret; - /* Reset controller */ - setbits_le32(&ehci->usbcmd, CMD_RESET); - - /* Wait for reset */ - if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) { - printf("Stuck on USB reset.\n"); - return -ETIMEDOUT; - } - clk_release_bulk(&p->clks); return 0; } -- cgit v1.2.3 From ed733d40ec3279fe8425becbe0552a2974051193 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 7 Apr 2025 11:54:26 +0200 Subject: usb: host: ehci-msm: Register ULPI PHY through NOP wrapper The UCLASS_USB device is removed and rebound each time you run "usb stop" followed by "usb start", or when you switch between USB device and USB host mode. Unfortunately, this causes issues with the current ehci-msm driver: In ehci_usb_remove() we call generic_shutdown_phy(), but at that point the ULPI PHY we registered in ehci_usb_of_bind() was already removed again by the DM core. Fix this by adding a UCLASS_NOP driver that keeps the PHY driver bound permanently, and then just re-probe the actual USB part. Reported-by: Jianfeng Zhu Closes: https://lore.kernel.org/u-boot/OSQPR04MB774067EBEEADD714EFE18C2A90882@OSQPR04MB7740.apcprd04.prod.outlook.com/ Signed-off-by: Stephan Gerhold Acked-by: Caleb Connolly Tested-by: Sam Day Link: https://patch.msgid.link/20250407-ehci-msm-fixes-v1-6-f8b30eb05d07@linaro.org Signed-off-by: Casey Connolly --- drivers/usb/host/ehci-msm.c | 107 +++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 42 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 659a917ad27..8aeb6a91556 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -25,6 +25,9 @@ struct msm_ehci_priv { struct ehci_ctrl ctrl; /* Needed by EHCI */ struct usb_ehci *ehci; /* Start of IP core*/ struct phy phy; +}; + +struct qcom_ci_hdrc_priv { struct clk_bulk clks; }; @@ -54,34 +57,20 @@ static int ehci_usb_probe(struct udevice *dev) struct ehci_hcor *hcor; int ret; - ret = clk_get_bulk(dev, &p->clks); - if (ret && (ret != -ENOSYS && ret != -ENOENT)) { - dev_err(dev, "Failed to get clocks: %d\n", ret); - return ret; - } - - ret = clk_enable_bulk(&p->clks); - if (ret) - goto cleanup_clocks; - hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength); hcor = (struct ehci_hcor *)((phys_addr_t)hccr + HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); ret = generic_setup_phy(dev, &p->phy, 0, PHY_MODE_USB_HOST, 0); if (ret) - goto cleanup_clocks; + return ret; ret = board_usb_init(0, plat->init_type); if (ret < 0) - goto cleanup_clocks; + return ret; return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0, plat->init_type); - -cleanup_clocks: - clk_release_bulk(&p->clks); - return ret; } static int ehci_usb_remove(struct udevice *dev) @@ -101,7 +90,6 @@ static int ehci_usb_remove(struct udevice *dev) if (ret < 0) return ret; - clk_release_bulk(&p->clks); return 0; } @@ -117,24 +105,6 @@ static int ehci_usb_of_to_plat(struct udevice *dev) return 0; } -static int ehci_usb_of_bind(struct udevice *dev) -{ - ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev)); - ofnode phy_node; - - if (!ofnode_valid(ulpi_node)) - return 0; - - phy_node = ofnode_first_subnode(ulpi_node); - if (!ofnode_valid(phy_node)) { - printf("%s: ulpi subnode with no phy\n", __func__); - return -ENOENT; - } - - return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy", - phy_node, NULL); -} - #if defined(CONFIG_CI_UDC) /* Little quirk that MSM needs with Chipidea controller * Must reinit phy after reset @@ -147,17 +117,10 @@ void ci_init_after_reset(struct ehci_ctrl *ctrl) } #endif -static const struct udevice_id ehci_usb_ids[] = { - { .compatible = "qcom,ci-hdrc", }, - { } -}; - U_BOOT_DRIVER(usb_ehci) = { .name = "ehci_msm", .id = UCLASS_USB, - .of_match = ehci_usb_ids, .of_to_plat = ehci_usb_of_to_plat, - .bind = ehci_usb_of_bind, .probe = ehci_usb_probe, .remove = ehci_usb_remove, .ops = &ehci_usb_ops, @@ -165,3 +128,63 @@ U_BOOT_DRIVER(usb_ehci) = { .plat_auto = sizeof(struct usb_plat), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; + +static int qcom_ci_hdrc_probe(struct udevice *dev) +{ + struct qcom_ci_hdrc_priv *p = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, &p->clks); + if (ret && (ret != -ENOSYS && ret != -ENOENT)) { + dev_err(dev, "Failed to get clocks: %d\n", ret); + return ret; + } + + return clk_enable_bulk(&p->clks); +} + +static int qcom_ci_hdrc_remove(struct udevice *dev) +{ + struct qcom_ci_hdrc_priv *p = dev_get_priv(dev); + + return clk_release_bulk(&p->clks); +} + +static int qcom_ci_hdrc_bind(struct udevice *dev) +{ + ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev)); + ofnode phy_node; + int ret; + + ret = device_bind_driver_to_node(dev, "ehci_msm", "ehci_msm", + dev_ofnode(dev), NULL); + if (ret) + return ret; + + if (!ofnode_valid(ulpi_node)) + return 0; + + phy_node = ofnode_first_subnode(ulpi_node); + if (!ofnode_valid(phy_node)) { + printf("%s: ulpi subnode with no phy\n", __func__); + return -ENOENT; + } + + return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy", + phy_node, NULL); +} + +static const struct udevice_id qcom_ci_hdrc_ids[] = { + { .compatible = "qcom,ci-hdrc", }, + { } +}; + +U_BOOT_DRIVER(qcom_ci_hdrc) = { + .name = "qcom_ci_hdrc", + .id = UCLASS_NOP, + .of_match = qcom_ci_hdrc_ids, + .bind = qcom_ci_hdrc_bind, + .probe = qcom_ci_hdrc_probe, + .remove = qcom_ci_hdrc_remove, + .priv_auto = sizeof(struct qcom_ci_hdrc_priv), +}; -- cgit v1.2.3 From 934647d49c61f9405767bd36da3bba06a40cf346 Mon Sep 17 00:00:00 2001 From: George Chan Date: Tue, 21 Oct 2025 00:23:59 +0800 Subject: usb: gadget: Introduce usb gadget vendor/product default id for ARCH_QCOM Currently vendor/product id are both 0, and that might not as we want. Set to some arbitrary known value that we can make it work more smoothly. Reviewed-by: Mattijs Korpershoek Acked-by: Mattijs Korpershoek Reviewed-by: Neil Armstrong Signed-off-by: George Chan Link: https://patch.msgid.link/20251021-sc7180-minor-v1-2-9fe33c73365e@gmail.com Signed-off-by: Casey Connolly --- drivers/usb/gadget/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index e845e46e0b7..008f8c99a58 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -60,6 +60,7 @@ config USB_GADGET_VENDOR_NUM default 0x0955 if ARCH_TEGRA default 0x1f3a if ARCH_SUNXI default 0x2207 if ARCH_ROCKCHIP + default 0x18d1 if ARCH_QCOM default 0x0 help Vendor ID of the USB device emulated, reported to the host device. @@ -87,6 +88,7 @@ config USB_GADGET_PRODUCT_NUM default 0x350b if ROCKCHIP_RK3588 default 0x350c if ROCKCHIP_RK3528 default 0x350e if ROCKCHIP_RK3576 + default 0x4ee0 if ARCH_QCOM default 0x0 help Product ID of the USB device emulated, reported to the host device. -- cgit v1.2.3