diff options
| author | Tom Rini <[email protected]> | 2025-10-30 08:03:02 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-10-30 11:06:44 -0600 |
| commit | 08bf42e1faa4411cd347c2e370da790a0116e318 (patch) | |
| tree | cc953ba9176fd10d374b250a04c5457c585be6c0 /drivers/usb | |
| parent | 557606968646a5215b656e0e1e8927e1902f32bf (diff) | |
| parent | 934647d49c61f9405767bd36da3bba06a40cf346 (diff) | |
Merge tag 'qcom-for-2026.01-rc2' of https://source.denx.de/u-boot/custodians/u-boot-snapdragon
A variety of Qualcomm features/fixes for this cycle, notably with a few
new platforms gaining support:
* Initial support for SDM670 (similar to SDM845), SM6350, and SM7150
platforms is added
* USB and UART issues on MSM8916 are addressed (improving stability/
reliability)
* Firmware loading is implemented for the GENI serial engine, this is
used on some platforms to load firmware for i2c/spi/uart to work
Some additional patches like binman support for building MBN files still
need some additional work.
CI: https://source.denx.de/u-boot/custodians/u-boot-snapdragon/-/commit/8ef6ac07b35e39a57501554680bbf452e818d3e3/pipelines?ref=qcom-main
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/gadget/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-msm.c | 146 |
2 files changed, 69 insertions, 79 deletions
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. diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index a759aea9db3..8aeb6a91556 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -24,10 +24,11 @@ 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; +}; + +struct qcom_ci_hdrc_priv { + struct clk_bulk clks; }; static int msm_init_after_reset(struct ehci_ctrl *dev) @@ -56,64 +57,31 @@ 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); - 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); - if (ret) - goto cleanup_core; - 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_iface; + return ret; ret = board_usb_init(0, plat->init_type); if (ret < 0) - goto cleanup_iface; + return ret; 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); - return ret; } 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); - - clk_disable_unprepare(&p->iface_clk); - clk_disable_unprepare(&p->core_clk); - ret = generic_shutdown_phy(&p->phy); if (ret) return ret; @@ -122,15 +90,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; - } - return 0; } @@ -138,38 +97,14 @@ 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 == (void *)FDT_ADDR_T_NONE) + 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; } -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 @@ -182,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, @@ -200,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), +}; |
